Skip navigation.

Claws, fangs, fur...

...the bear essentials

Posts tagged with "Web"

It isn't paranoia if the danger is clear and present

, , , ...

You have your custom virus scanner and your custom firewall active, right? This threat will make all of that mean nothing at all. http://www.adobe.com/support/security/bulletins/apsb09-15.html

Arbitrary code execution on a web page visitor's computer by sending malicious javascript through Adobe Flash.

Guess what problems will arise with local off-line storage in HTML5?

Thus, by default, treat the web and every page on it as a potential threat. It's a dangerous place and people want to wreak havoc.

  • Turn off plug-ins and javascript unless you trust the page and need the functionality.
  • Make it easy on yourself to turn them off and on based on what page or domain you visit: use the Opera browser.
  • The less fortunate that get stuck with Firefox can use the NoScript extension.
  • For those who are forced to use Microsoft's excuse for a web browser... avoid the web altogether.

Unobtrusive Javascript

, ,

There are scripts we wish to use only in certain browsers... mostly because other browsers don't need them. And when we do need those scripts, they shouldn't obtruse on the other browsers. The methods used to supply scripts this way are called "unobtrusive".

Why?

Because we do want to separate behaviour from mark-up and we don't want browsers yelling at us about stuff they don't need anyway.

Like what?

  • Like scripts that simulate CSS-defined hover behaviours so they work in MSIE6 and 7, too. Or like scripts that simulate Web Forms 2.0 behaviour in MSIE6 and 7. (Both of these are supported natively by Opera. Firefox only supports the first, but the second is expected soon.)
  • But also like a braille-reader that doesn't know about Javascript at all, or a search spider crawling and indexing our site.


How?

First we remove any and all in-line javascript handlers from the (x)html source. If the other browsers aren't going to use it, they shouldn't see it.

Then we specify that only the addressed browser is going to read the script. Since in most cases MSIE is the only odd one out, MS has been helpful enough to provide Conditional Comments, that are used by MSIE only. They work like this:

<!--[if lte IE 7]
<script type="text/javascript" src="MSIEScript.js"></script>
[endif]-->


Of course this works with in-page script as well:

<!--[if lte IE 7]
<script type="text/javascript">
/* <![CDATA[ */
alert('MSIE-only XHTML-javascript');
/* ]]> */
</script>
[endif]-->


or, for good-ole html:

<!--[if lte IE 7]
<script type="text/javascript">
alert('MSIE-only HTML-javascript');
</script>
[endif]-->


Thirdly, we reattach the events we removed in the first step. All modern DOM2 browsers use the W3's addEventListener for that, except MSIE, whose programmers in all their wisdom decided to create their own implementation known as attachEvent. And no, they didn't add addEventListener as a courtesy method either.

So we figure out which method is used by the browser. A nice way for doing this was described by someone else on the net: JavaScript Tip #1: Speed Up Object Detection. I'll just take it one step further:

<script type="text/javascript">
var addEvent;
if (document.addEventListener) {
 addEvent = function(element, type, handler) {
  element.addEventListener(type, handler, false);
 };
} else if (document.attachEvent) {
 addEvent = function(element, type, handler) {
  element.attachEvent("on" + type, handler);
 };
} else {
 addEvent = function(element, type, handler) {
  element["on" + type] = handler;
 };
}</script>


Will this work? Not all the time. There's a problem with parameters: the above-mentioned methods don't allow the immediate passing-through of parameters. So we have to find a way to read them from the window.event object. Especially when we're hovering or clicking and we want to know which element was hovered or clicked. Unfortunately, MSIE doesn't follow the DOM2 recommendation, so once more we need an exception.

<script type="text/javascript">
function readEventTarget(e){
 if(!e){
  if((window)&&(window.event)){
   e=window.event
  }else{
   return false
  }
 }
 if(e.target){return e.target}
 if(e.srcElement){return e.srcElement}
 return false;
}</script>


Will this work? Again, not all the time. In MSIE and Firefox, in case of an LI-element with only block-level elements inside it, the hover and click will only reach the block-level elements and not the LI-element. In Opera however, the interaction will reach the LI-element. So once more we need to open our bag-o-tricks:

Instead of adding static events and figuring out who called it, we can add "live" events. This is done by creating functions on the fly. Disadvantage: memory footprint.

<script type="text/javascript">
function init(){
  if((window)&&(document)&&(document.childNodes)){
    var c,d=document.childNodes;
    for(var i=0; i<d.length; i++){
      c=d[i];
      if((c)&&(c.tagName)&&(c.tagName=='UL')){
        c.onmouseover=new function(){
          window.status=('Number of items in list: '+this.length);
        };
      }
      c=null;
    }
  }
}</script>


(Of course we can combine this with a static event by calling it from inside the new function.)

See that 'this' thing in there? Why can't we simply ask for c.length, since it's supposedly the same object? Because that 'c' is a variable that holds a value only inside that loop. Once the new function gets called, the loop no longer exists, thus the 'c' variable no longer points to anything. Querying a length of nothing results in an error.

Instead we query the length of the 'this' object. At the moment of function execution, 'this' refers to the executioner, which happens to be the UL.

This by the way can lead to a whole bunch of confusion, especially if it isn't apparent which object is the executioner.




There's a lot more to say about unobtrusive javascript. The main idea is not to bog down a browser with functions it either can't use anyway, or supports natively.

I hate MSIE

, , ,

Again.

Why?

First of all, because even the latest version (7) of this browser thinks it is impossible to hover a cursor over anything other than a hyperlink. No, it says, you cannot hover your cursor over an image. No, it isn’t possible to hover over a list item. Nope, hovering over a button does not exist.

Sure, you can define these behaviours in the html code… but that’s SOOOOO 90s! Ef off! We put these behaviours into our CSS. Right?

Yes, and that’s exactly where MSIE4, 5, 5.5, 6 and yes, even 7 go wrong.

(Edited to add the following: my latest tests show that MSIE 7 does perform hover actions on elements other than hyperlinks. Previous versions refused.)

Does the competition allow CSS-specified hover behaviours over other things than a hyperlink? Sure they do! Anything we could possibly desire and code into a web page is hoverable, according to Opera, Firefox, Safari, Camino, K-Meleon, Konqueror, Netscape, Mozilla.

Thank you, Microsoft, for refusing to implement standard behaviour.

Can we solve this stupidity?

Say, “yes Junior”! (”Yes, Junior!”)

We can add a bit of javascript to our web page, specifically for MSIE. We can hide it from decent browsers by using Conditional Comments (another MS invention, this time it cames in handy).

And here comes the second reason for my renewed hatred of MS’s poor excuse of a web browser:

Because none of the other browsers require Javascript for the hover behaviour, we want to inject it completely unobstrusively. Meaning: the decent browsers don’t get to see any of the javascript. Meaning: any behaviour that needs javascript will have to receive it… by javascript.

Can we do that? Yes, we can!

Of course, MS implements its own method. Instead of following the W3 recommendation of the DOM-2 object model for connecting events to HTML (element.addEventListener), it uses its proprietary method (element.attachEvent), and it refuses to implement the standard method. Thank you once more, MS, for making my life harder.

However, we can work with that kind of arrogance. Since the script only needs to work in MS anyway, we shouldn’t really be bothered. Annoying, yes.

First we attach our own custom initialisation to the loading of the page. Here we find hate-reason 2.1: we can’t attach it to the document, no, MSIE wants us to attach it to the bloody window. Otherwise, the initialisation simply won’t be executed. Why is this a problem? Because the window isn’t part of the page! It’s part of the browser and the page author should never be allowed to change the user’s browsing environment! So thank you, MS, for impeding on the user’s independence!

Second, we write our custom initialisation. We tell it to find the elements we wish to hover and attach the same javascript function to their hover event. There we find hate-reason 2.2: we can’t use a predefined function. Instead we have to create the function for every element. Bloody waste of memory.

Reason? Parameters. When using a predefined javascript function to hover an element, we have to pass the element itself to the function, so it can figure out which element was hovered. The Javascript language definition (a.k.a. Ecmascript) however prevents the author from supplying this information during the attachment process… which is exactly where we want to supply it!

So the hover function doesn’t know what to hover. Can we get around that? Sure we can! We just call up the window event and figure out what element was hovered! Even MSIE can do that! Right?

Kind-of.

MSIE’s implementation of the event object differs greatly from the W3 DOM2 standard. First of all, it has no target property. It does have a proprietary srcElement property however, that fills this omission. (Now the nice thing to do, MS, is to add a target property anyway, and keep the srcElement for backwards compatibility.) But what does this propery say? Does it say what element was hovered?

Kind-of.

In MSIE, the hovering doesn’t bubble up to its parent. So for very simple, flat web pages this might do. But it won’t even work when hovering a list item with a block inside of it… because it will indicate the block was hovered instead of the list item.

Well, isn’t that enough? No! We don’t want to attach this hovering behaviour to every possible element inside a list item… We want the hovering on the list item itself! Exactly the same way it works when we specify an onmouseover event on the list item. Please don’t tell me you can do the one but not the other, MSIE!

Helas.

So strike the predefined function. Instead, we use an in-line, newly created function for each list item. Great.

Thank you, Microsoft, for increasing the amount of memory used by a web page. Thank you, for forcing us to increase the complexity of our scripts. Thank you, for impeding on the user’s independence. Thank you, for assuming only hyperlinks can be hovered.

Thank you, for making decent, well-willing web authors waste 3 days trying to find ways around your crummy, short-sighted omissions.

xhtml and in-page scripts / styles

, , , ...

So you’ve decided to write XHtml instead of Html. And all of a sudden you realise: my in-page scripts and styles stopped working! (Or at least they stopped validating.)

Why, you ask?

Mostly because scripts and styles use characters that Html doesn’t really like, for instance the &. This will break validation and in some browsers it will prevent scripts and styles from being interpreted at all.

To solve this, the XHtml 1.0 recommendation describes three methods:
  1. omit any usage of html entity references inside your scripts
  2. move your scripts from in-line to a separate file
  3. escape the entire script by marking it as CDATA


The first method changes the scripts and makes them unusable.

The second method is nice and best practice, but isn’t always useful.

The third method doesn’t work.

What?

The third method doesn’t work. At least not in any current browser I’ve tested.

Why?

Let’s see how the recommendation sees this escaping:

<script type="text/javascript">
<![CDATA[
alert('hello, world!');
]]>
</script>

Guess what? Most current browsers don’t accept the code for specifying a CDATA block inside a javascript block. So they won’t recognise the script, won’t execute it, or may generate lots of errors.

Is there a solution? Yes, there is! Remember from scripts in Html, that we used to add Html comment tags to hide the scripts from unscripted browsers? We can do the same here, with the same effect!

<script type="text/javascript">
/* <![CDATA[ */
alert("hello, world!");
/* ]]> */
</script>

Easy, no?

And we can do the exact same with our style block, too:

<style type="text/css">
/* <![CDATA[ */
html { background: black; }
/* ]]> */
</style>

Now the blocks validate and will get executed.

This method was tested in:
  • Opera 9.2
  • Firefox 2.0
  • K-Meleon 1.1
  • MSIE 6
  • MSIE 7

Google Maps Sucks

, , , ...

For community websites I’m building a member locator using Google Maps to allow members to locate themselves and others around them. Pretty neat.

What isn’t neat is the following: the Google example code shows to use an XHTML doctype. Yay! Erm, no. See, in order for Microsoft’s excuse for a web browser to understand XHTML, it has to treat it as HTML, rendering all the advantages of using XHTML completely useless. The server admins know that, and instead of sending XHTML as XHTML, they send it as HTML. So the document claims to be XHTML, while both the server and the browser assume it to be HTML.

Big difference? Big difference!

Why?

Because XHTML is much, much more strict than HTML, and much, much more extensible. It’s a web author’s godsend, and a browser’s nightmare at the same time.

As said, Google Maps examples show that authors should be using XHTML files. Since I’m testing my scripts in decent browsers (Firefox, Opera), I assumed that it would be no problem to have my server send them as XHTML. Yes, I had to be the wise guy who actually tried to adhere to the standards as recommended. Took me 4 hours to recognise Google’s mistake, and 2 seconds to correct it.

The symptom: my browser wouldn’t load some of Google’s scripts, indicated by its complaining that my code was calling objects that didn’t exist.

The problem: Google’s Map scripts use a function that overwrites the running application with new code. (For insiders: check out the GScript function.)

Why is this a problem? Because the running application is being erased and overwritten by itself. XHTML is protected from such malpractice. Thus Google’s code won’t work.

HTML, as said, is far less strict. HTML browsers assume that the new code is going to be appended to the existing application, instead of overwriting it. So HTML browsers are mis-executing code which then results in a desired behaviour, while XHTML browsers are correctly exucting the same code, which then results in undesired behaviour… nice catch-22.

Google Maps documentation doesn’t talk about this catch. They probably assume everyone sends their XHTML documents as HTML, just like Microsoft. Their examples are 2 years old, and I’ve seen complaints about this same topic as far back as 18 months.

By advocating mis-use and malpractice, Google promotes the confusion about web standards, and suports Microsoft’s wish to dominate the web. I wonder whether Google has stock in Microsoft.

I haven’t found a strict XHTML solution yet, but if I did, it wouldn’t work in Microsoft’s poor excuse of a browser anyway.

Data URIs and MSIE

, , , ...

No match.

Bloody briljant. In 1998 some people came up with a way of enclosing a file source into an HTML or CSS file so you wouldn’t need to link to an outside file.

Where does this come in handy?

Well in all those pretty e-mails of course, sent to you by a handful of spammers and a friend or two. We can now send the pretty image we wish to show as part of the HTML itself, so we don’t need to perform dirty tricks like cross-referencing attachments or bypassing network firewalls.

Makes rich-text e-mails safe again.

Guess which browser doesn’t support Data URI’s?

Yup, the world’s most used one. Thank you, Microsoft, for refusing to improve the security of your systems since 1998.

Description: http://en.wikipedia.org/wiki/Data:_URI_scheme
Specification: http://tools.ietf.org/html/rfc2397
Download Opera, the fastest and most secure browser