Friday, October 5, 2007

Two (appropriately) small Opera Mini tips

Opera Mini has some funny rules relating to image display. I was doing some work for a partner company and was staring at this line of code wondering why Opera Mini wasn't displaying it:

<img src="http://www.blogger.com/partner.gif" alt="partner" height="25" width="60" /> (doctype is HTML 4.01 since you ask, works fine so don't knock it)

I noticed that the partner's graphics people had saved the GIF with an animation setting ( a surprisingly comment defect) so I recreated it without. No joy. Didn't work as a PNG. Then I had a brainwave: I deleted the alt attribute and lo and behold Opera Mini displayed the image. Not completely unreasonably, the Opera Mini proxy displays the ALT attribute of an image if present, but if it isn't it assumes that there might be some information required by the user in the picture and displays it. While not unreasonable, this is still a poor decision as it means I now have to generate usability-deficient HTML in order to achieve a desirable visual effect.

The other tip is in the same vein: creating horizontal rules in Opera Mini requires a trip back in time to 1997. OM ignores border directives in CSS, but respects background colour, so you can't mark the bottom of a div like this: div {border-bottom: 1px solid black; background-colour: ghostwhite} - OM will colour the div, but not the bottom. In order to get this effect you have to stick a 1 pixel tall image (again beware, don't call the image something like "spacer.gif" as the algorithm finds those and removes them from the rendering) in a div or its own. OM will shrink the image to a centred 50% or so of the screen but you can now colour the background to match and OM will dutifully render the div to the full width of the screen. Again, not recommended as scalable code for other browsers, but should you ahve the luxury of creating an OM-specific rendering, this does help break up the page visually.

Obviously neither of these tips are relevant for Opera Mini 4 which is an entirely different issue. Equally now I've explained how to fool Opera Mini, Opera's proxy engineers might fix the proxy to ignore 1px divs.

Tuesday, August 21, 2007

Silence is broken: a pair of browser bugs

I know this blog has nearly gone abandoned: I'm currently working on a big Mobile Ajax project and consequently most of what I do belongs to someone else (it's that sort of contract). I may have to restrain myself to quiet musings on mobile interactivity rather than actual source-code, although you'll all be able to rip that when the site goes live...

Anyway, as a peace offering here are two recently noted browser bugs:

1. The N73 (N73-1/33.0638.0.0.1 - I'm keeping my firmware stock) has a nice little bug involving checkboxes. If you select a checkbox and then move the cursor out the checkbox deselects. It's not just a visual effect, the form element is not set to "on" when the form is submitted. Double-clicking (so the control looks checked and then unchecked) has the opposite effect: moving the cursor out switches the control to checked, and the form element's state to "on". We've had to switch to using radio buttons in a single-item group to get around this problem.

2. Netfront 3.3 refuses to display or load iframes unless they have a width set. Width is only optional according to the DTD, but not according to Netfront...

Thursday, June 28, 2007

Having made a tit of myself

...over onChange (read the standards before moaning Smith), I'm wary of dumping my latest S60 browser woe in public, buuuut I'm fairly sure I'm on firmer ground here. It looks like there's no way to query the styles of an element beyond the positional shortcuts: getComputedStyle() throws some sort of exception (I can't get window.onerror to respond either, so I'm in the dark as to what it's suffering from) and element.style is null - which is kind of consistent with the rest of the world. getPropertyValue doesn't work either, but that's not a huge surprise as it doesn't work anywhere else either.

This isn't quite as critical a problem as the lack of any way to query what's in a text box while the user types (and it is still a problem: the text box doesn't want to respond to key events either) but it's still annoying. All I want to do is fake an opacity fade-out (think scriptaculous) by querying the style for colour, then making it closer to the target colour bit by bit. No dice.

In other news I'm loving the meta-ness of Opera Mini 4 beta. The new version now supports XMLHttpRequest. Which means that Ajax calls are served as plain HTTP requests, causing a complete reload of the page. I can totally understand why the Mini team should have put this in, but it's a curious state of affairs to be sure.

Wednesday, June 27, 2007

More thoughts on onChange

I was wrong below. Painful that, but true. Sorry Nokia! Nokia's implementation of the onchange event is entirely correct according to the W3C's recommendations. The best summary is from this working group note on DOM Level 3, but it's essentially unchanged since the HTML 4 spec:

change
A control loses the input focus and its value has been modified since gaining focus.
Now what's odd about that is that virtually no browser actually implements the change event that way: select drop-downs wouldn't be able to react when you release them (because technically they still have focus - or does that count as losing focus even though the element is still selected?) and autocomplete wouldn't work so nicely. Having said that it looks like both Google and script.aculo.us do a certain amount of trickery to ensure that they get the content of the text box. Google's autocomplete script appears to throw focus on and off of the element with keypresses (appears to, the Google obfuscated Javascript is very hard to follow) while scriptaculous adds a keypress event listener. I'm going to go off and try that but I'm not hopeful as the Symbian input method editor (IME - new jargon learned today!) seems to block all key events and only recognises onclick.

Tuesday, June 26, 2007

Browser fragmentation: onchange fails in S60 Browser

We've found an interesting problem with the S60 browser. We're trying to put together an auto-complete form for a page, using Ajax. Possibly this is oldest Ajax pattern of all, as it's the one that appeared with Google Suggest: the user types in a few characters and the browser goes off and fetches some proposed completions.

On the early firmware N95 we have it appears that the S60 browser is incapable of detecting that the user has entered text. None of the form or key events work, with the exception of onfocus and onblur. I put a Javascript test page together that scans the text field repeatedly while the form element is focussed, and it appears that the browser is unaware there's anything in the text field until the user blurs it. One of my colleagues suggested that's because the operating system doesn't release the text to the browser until all the potential T9 completions and multi-key presses have been processed. This makes sense, but doesn't help much.

Interestingly Opera works fine, but it looks like Opera wrote their own text-input-handling routines: possibly to get away from this issue?

As I say, I only currently have a beta N95 to hand. I'd be interested if this issue persists in the production versions and whether anyone has found a workaround.

UPDATE: does the same in the S60 SDK emulator. Peculiar.

UPDATE AGAIN: The S60 Webkit source reveals the following:

From: FControlInputSkin.cpp
// CFormInputSkin::WaitForLastCharCommit - CIdle->callback function that waits for the last character to be commited
// if the text is changed then the text is set to the inputskin and and event is generated into KWQLineEdit to handle
// the textchanged event. The textwidget is deleted after that

So it looks like it's an unholy collaboration between the browser and the OS. Unless I'm reading the wrong file...

Thursday, June 21, 2007

Updates are coming

I've been slightly distracted by trying to form a company, so bear with me. In the meantime let's spare a thought for usability, notably Greg Papadopoulos' thoughts on usability. This one had me scratching my head. Why are Sun trying to position themselves as a usability company? I last saw anything with a Sun GUI on it in 1996. I'm sure someone somewhere still uses CDE but they're about as relevant as OS/2 users.

Papadopoulos's point appears to be revving up the old network computer/smart device thing that Sun have repeatedly tried to claim as their territory. For those of us with experience of the mobile industry this has been a legacy of seven years of ever-worsening fragmentation between Java implementations and multiple JSRs. Put bluntly: Sun has done an awful job of maintaining usability across Java, so why should we believe their tired claims about network computers?

If I was Sun I'd be very worried: the smart client work is moving to web browsers and Sun doesn't have a web browser, or any part of the LAMP (or LAMR) stack, come to think of it. Java will probably find a happy niche as another legacy enterprise programming environment (like C++ was before Java took over), but it's very hard to see how they'll make money out of it.

Wednesday, June 13, 2007

Minim takes wing

I've properly objectified and trimmed the minimal Ajax example I started work on earlier. It's now 336 bytes. My target is to keep the whole thing to under 2k, so I have 1712 bytes to put some other functions in.

It now looks like this:


function TinyAjax(callback) {
this._req = null;
this._sc = function() {
if (_req.readyState == 4 && _req.status == 200) {
callback(_req.responseText);
}
};

this.ajaxRequest = function(url) {
_req = new XMLHttpRequest();
_req.onreadystatechange = this._sc;
_req.open("GET", url, true);
_req.send();
} ;
}


UPDATE: the above has a scoping error in it and _req ends up in the global scope. Ooops (or rather, not OOPS). I am fixing it this evening along with a periodical updater object, which is also bigged down witha weird scoping issue.

Usage is simple: you pass the TinyAjax constructor a function that will handle the response then call the desired URL with TinyAjax.ajaxRequest() method. The class will then do all the work for you.

I haven't yet got hold of a Windows Mobile device to test on, so this currently only works with standards favouring browsers like Opera and S60. When I get one I'll add whichever object Windows thinks it wants.

It's now in a file called minim.js and can be got from here: http://slackr.eu/m/src/minim.js.txt