Abusing text-shadow for fun and profit

A while back, when Opera 9.5 was in development, we gained support for [getters and setters](http://ejohn.org/blog/javascript-getters-and-setters/), and I needed some smoketest to check whether they worked as advertised.
Around the same time, we also added support for text-shadow, as outlined in the documentation for [Presto 2.1 standards support](http://dev.opera.com/articles/view/presto-2-1-web-standards-supported-by/#css3) (Presto is the core engine of Opera, currently in version 2.1)
So, I ended up testing both at once. [See the example](http://virtuelvis.com/gallery/text-shadow/). The demo fades some text in and out of the screen, simultaneously deblurring the text as it becomes visible. The fading itself is fairly trivial, with the animation library used taking care of the work.
### The script
I’ll keep this explanation brief, and gloss over some of the details, but: The majority magic happens in the getters and setters defined. Somewhere in the inlined code on the page, you’ll find this:
var e = CSSStyleDeclaration.prototype;
// … other getters and setters
e.__defineGetter__(“blur”,function(){ return this._blur_||0; });
e.__defineSetter__(“blur”,function(val)
{
this._blur_ = val;
this.textShadow = this.shadowX+” “+this.shadowY+” “+val+” “+this.shadowCol;
})
In the actual code, `this.shadowX`, `this.shadowY` and `this.shadowCol` are also attained through getters and setters on a CSSStyleDeclaration, but for the purpose of explaining, you can assume them being hardcoded to 1000px, 0 and #fff, respectively.
So, when the animation library is initialized and animations are set up, we tell it to animate the `blur` property of the affected element’s style
var st = document.getElementById(‘foo’).style;
var anim = new Animator(st,1000,15,
function(){ setTimeout(moveOut,1750) },
forceRepaint);
anim.addProperty(“blur”,12,1,”px”);
So, when the animation is run, the library iterates through all the properties of the animation, and when reaching the `blur` property, it sets it, but what is actually set is the blur value of the text-shadow, e.g. 1000px 0 3px #fff
### The CSS
For the purposes of the CSS, I conjured up a somewhat more minimal example, in the form of a navigation list.
[Try out the example here](http://virtuelvis.com/gallery/text-shadow/navigation-list)
What is happening in this example is pretty much analogous to what is going on in the animated demo. When you hover an element in the list, that element gets some focus, while the rest of the elements are blurred to bring attention to what you currently are hovering.
The first CSS rule to mind here is:

li {
font-weight: bold;
padding: 0.5em 0.5em;
display: block;
overflow: hidden;
color: #333;
background: hsl(40,15%,90%);
border: 2px outset #aaa;
}

Specifically, the `overflow: hidden` rule, which ensures that we clip the element’s box if content overflow it. Next, we’re applying a rule to all list elements when the list itself is hovered:
ul:hover li {
text-indent: -8em;
text-shadow: 8em 0 0.33em #333;
background: hsl(40,15%,40%);
}
The point of the rule is to move the text out of the element’s box, by setting text-indent to -8em and instead setting a text-shadow offset as 8em. Next up here is setting some mild blur (If you can call 0.33em, which I used for dramatic effect), and the same color as the text.
Finally, for this example, the following rule resets the text-shadow to something more sensible:
ul li:hover {
text-indent: 0;
color: #eee;
text-shadow: 1px 1px 2px #333;
background: hsl(40,15%,60%);
}
### Closing words
While you can probably do some real cool stuff, and create low-cost effects, I would advise against using it for production use: In both examples, text will become invisible if text-shadow is not supported. From what I have been able to gather, only a limited set of browsers [support text-shadow](http://www.css3.info/preview/text-shadow/)
Either way, it might be fun in 2014 when browsers have caught up to the next level of CSS.

Why Facebook might want to avoid volunteer translations

I am not to be found on Facebook (in fact, I spent three days of mailing back and forth with them, before they wanted to accept that, yes, I *really* want to completely nuke my account). But via “ITavisen”:http://www.itavisen.no/sak/782354/ I found out something curious about their “Terms of Use”:http://www.facebook.com/terms.php
Facebook are now providing users with localized ToS, like this “Norwegian translation”:http://nb.facebook.com/terms.php. And they are apparently relying on volunteers to do this work. Which, if you are a soulless Web 2.0 company with a ToS that reads like lawyer porn, probably is a very bad idea.
The “Google translation back into English”:http://translate.google.com/translate?u=http%3A%2F%2Fnb.facebook.com%2Fterms.php&hl=en&ie=UTF8&sl=no&tl=en will miss some nuances of what’s wrong with it, but it should be good enough. Skim the headings of that translation.
Did you find it? No, not the runs of untranslated text, but the big fat heading saying *”Press if you’re a jerk”.*
Yes, really. It really does say “Trykk hvis du er en dust”, which translates into “Click if you’re a jerk”. And it’s not the only brainfart here. The entire section on indemnity has been replaced with the following run of text:
bq. Du lover å være snill og grei å følge alle regler for bruk av facebook
The wording is something you would typically find in children’s books, and translates to:
bq. You promise to be a good boy or girl, and promise to follow every rule for use of Facebook
I could comment further, but I’ll let the one occurence of “Lalaala” accompany my giggle. Morale of the story is: Hire translators, and actually do some QA.

Note to self about mounting problems

This is just a small note to my future self, for the next time I encounter seemingly random invalid mount operations, or other mount failures in Ubuntu (Hardy Heron, in this case), for phone cards, usb drives et al. Remove the following line from /etc/fstab:
bc. /dev/sdb1 /media/cdrom0 udf,iso9660 user,noauto,exec,utf8 0 0
For what it’s worth, I have to do this because I have no optical drive in my laptop, and this line seems to be added, regardless of the presence of such a drive.

Why did you switch?

In 2004, I asked my readers “why they switched from IE”:http://virtuelvis.com/archives/2004/12/msie-switcher-stories
This question is worth repeating, but in a new context: Between 20 and 30% of my non-robot visitors are using an operating system other than Windows when visiting this site, and over the last 12 months, the Windows family of operating systems has seen a decline of over 2% of the visitor share to this site. I assume that many of these users once were Windows users, so I’d like to repeat the short set of questions:
# When did you switch?
# Which version of Windows did you switch from?
# Which OS did you switch to?
# Why did you switch to your current OS?
If you haven’t switched yet, but you’ve given it some thought, feel free to respond as well.

Autosizer 2, UserJS and cross-domain storage

Back in 2005, I wrote a UserJS named “Autosizer”:http://userjs.org/scripts/browser/enhancements/autosizer that enhances Opera’s behavior when you view a single image. The script from back then has one inherent problem, though; when you set a resize mode, it would be remembered on a per-site basis, instead of as a global option. Which, frankly, sucks, as I usually prefer a preference to be that, just a preference that sticks, whether I am viewing “infinite lolcats”:http://icanhascheezburger.files.wordpress.com/2008/06/funny-pictures-infinite-lolcat.jpg or “ray tracing examples”:http://upload.wikimedia.org/wikipedia/commons/e/ec/Glasses_800_edit.png
Enter Autosizer 2, which fixes this, through a hack, which either is really clever, completely insane, or both. First off, “download”:http://virtuelvis.com/download/2008/06/autosizer/autosizer.js and “install”:http://userjs.org/help/installation the user script. The script is a complete rewrite of the old script, and has been on a severe diet: There are now only two modes: View in original size, or Fit to screen.
h3. The hack: Iframes, error pages, invalid domains and cross-document messaging
The way this works is roughly:
# When an image is loaded, such as the two example images above, the script creates and injects an iframe pointing to http://0.0.0.0/img — an invalid URL
# Next, the other half of the script activates only on the URL mentioned above, and sets up a few listeners for cross-document messages. It recognizes three settings, one for setting Fit to screen, one for no fit, and one for just retrieving the current setting
# Every 300ms, the iframe will post a message to its parent window, with the current value of the setting.
# The event listeners in the parent window (the image) will, upon getting a message from the iframe set the correct sizing mode.
# The net effect of this is that we now have a cross-domain preference storage for UserJS.
What about security? Well, this is the catch, there is absolutely _no_ security here, so a user script author should never store anything here that is remotely private, nor should an author assume that data stored in this way are not corrupted: A web page can send and retrieve messages in just the same way a user script can.
So, how much data can you store? Well, you have an entire /8 to store cookies on, which is 16 777 216 domains, you can have 30 cookies per domain, of max 4096 bytes each. That is “1.87 terabytes”:http://www.google.com/search?num=100&hl=en&safe=off&client=opera&rls=en&hs=5KZ&esrch=BetaShortcuts&q=30%2A4096%2A16777216+bytes+in+terabytes&btnG=Search. Just don’t try. Or if you do, write a virtual filesystem implementation or something that gives you infinite geek points.
Should you want to mess around with the autosizer script, it’s licensed under the New BSD License. Enjoy.