Adding icons to bookmarklets … again

Show simple Demo

Yesterday I got a question on how to make my Bookmarklet-with-icon code work and sadly, it seems to be broken now. So I set out to find another method and strangely enough the solution that works with modern Firefox versions is quite simple and elegant:

Open the bookmarklet in "page mode" once after the user has added it as bookmarklet. This may sound like something that’s terribly hard to detect, but with a few simple tricks it’s not much of an issue: Mainly because you can make it so that the user barely notices if it fires to often.

  1. Just like the original bookmarklet-with-icon code, adding icons still relies on the behavior that a javascript: url which returns a string will cause the browser to display that string as a HTML document. So, the first step (again) is saving the HTML string somewhere. Of course, you can still add a bit of randomness, but for simplicity’s sake we’ll leave it out for now:
    <script>
      top["bookmarkletv2sample@tapper-ware.net"] = ''
        +'<!DOCTYPE html>'
        +'<html>'
          +'<head>'
            +'<title>My Bookmarklet</title>'
          +'</head>'
          +'<body></body>'
        +'</html>'
      ;
    </script>

  2. Now, we add the magic favicon sauce:
    <script>
      top["bookmarkletv2sample@tapper-ware.net"] = ''
        +'<!DOCTYPE html>'
        +'<html>'
          +'<head>'
            +'<title>My Bookmarklet</title>'
            +'<link rel="icon" href="http://www.my.domain/favicon.ico" />'
          +'</head>'
          +'<body></body>'
        +'</html>'
      ;
    </script>

  3. Like I said, we want that page to only appear very briefly, so we add a history.back(); call that will take us right back to the previous page. I’ve added a timeout as well, which is probably not necessary, but with hacks like that it’s better to err on the side of caution. It’s also a good idea to split the closing script tag to prevent any browser from misinterpreting it as the end of the current script block:
    <script>
      top["bookmarkletv2sample@tapper-ware.net"] = ''
        +'<!DOCTYPE html>'
        +'<html>'
          +'<head>'
            +'<title>My Bookmarklet</title>'
            +'<link rel="icon" href="http://www.my.domain/favicon.ico" />'
          +'</head>'
          +'<body>'
            +'<script>'
              +'window.onload=function(){'
                +'window.setTimeout(function(){'
                  +'history.back();'
                +'},250);'
              +'};'
            +'</scr'+'ipt>'
          +'</body>'
        +'</html>'
      ;
    </script>

  4. And that’s pretty much it for our magic assign-icon-from-within-bookmarklet page. Now we just have to change the actual bookmarklet to return that HTML string instead of running the bookmarklet code whenever a thusly-named HTML string exists on the current page. Assuming our bookmarlet is a plain old alert("This is my bookmarklet");void(0);, we have to wrap it into a little if-block like this:
    if(top["bookmarkletv2sample@tapper-ware.net"]){
       top["bookmarkletv2sample@tapper-ware.net"];
    }else{	
       alert('This is my bookmarklet');
      void(0);
    }


    which, written as a bookmarklet one-liner, turns into

    <a href="javascript:if(top['bookmarkletv2sample@tapper-ware.net']){top['bookmarkletv2sample@tapper-ware.net'];}else{alert('This%20is%20my%20bookmarklet');void(0);}">My Bookmarklet</a>

  5. If you put those blocks somewhere on your page it will already work… sort of: If you drag the link to your bookmarks-toolbar, then click it, you’ll briefly see an empty page and the icon will appear. Now, all we have to automate is that one click. Luckily, all we have to do for that is listen for a dragend event, which occurs whenever the user drags the link anywhere. It also occurs during any other drag operation but since that brief refresh is barely noticeable it doesn’t really matter if we try to assign the icon too often. All we have to do for that is add an ondragend attribute to the a element:
    ondragend="this.click();"


    Which finally turns our “A” element into this:

    <a ondragend="this.click();" href="javascript:if(top['bookmarkletv2sample@tapper-ware.net']){top['bookmarkletv2sample@tapper-ware.net'];}else{alert('This%20is%20my%20bookmarklet');void(0);}">My Bookmarklet</a>

And that’s all there is to it. Include the link and the script element on your page, tell the users that they should add it by dragging the link and that it won’t work on the current page, adjust favicon-url and exchange the example with your own JS code. Done.

Listening in on WebGL : WebGLProfiler

I’ve been trying to learn a thing or two about WebGL, but I’ve encountered a very simple problem: Most examples you find on the web have a very complex source code that is great for demonstrating how the particular framework the developer has written/used works, but usually not so great for learning WebGL itself.

For example take a look at this sample that often turns up when you ask about realtime shadows. It’s a beautiful little thing, but it uses Google’s O3D framework, so if you want to learn about the GL code involved, without learning about O3D, you’re pretty much out of luck.

So I decided to hack up something that can give me a runnable version of all the GL calls involved in this, complete with symbolic constants at least for the most common GL calls (have a look at the top of the source to see what arguments are currently resolved). It’s very hackish and may not always work perfectly (for example, it replaces all intervals and timeout with a value of 10000 so that you don’t get flooded with frame updates, meaning that it could take a while for what you’re interested in to appear), but it creates a WebGL program that’s strictly linear and pretty easy to read. Since it was built for my own use it also has some pretty ugly hacks that could be solved more elegantly with enough time (for example it checks for the document’s load state using an interval waiting for the title tag to appear), but it works. The resulting HTML page will have snapshots of canvases or videos embedded, while the images are links to the originals.

The big drawback so far is that you’ll only get the raw values of matrices, since these are not handled by WebGL, but by a few different libraries. It’s a big drawback, since it means that you will have to look them up in the original source code, but if they are probably named (global variable names are inserted by the profiler as comments and if there is none, you can always look at the names used inside the shaders), you can usually guess them pretty well.

I’ve wrapped the whole thing into a bookmarklet for easy use. When invoked, it will load the current document into the right frame, monkeypatch it and on first use of the webgl context start reporting to the left frame. The left frame will then contain a complete HTML document that you can just copy/paste and it will produce the same output as the original page. Be warned, it will VERY likely only work in current Firefox nightlies.

Perhaps the best way to illustrate it is showing the output of a few samples (look at the source):

You can find the bookmarklet at http://www.tapper-ware.net/data/devel/web/apps/JS.WebGLProfiler/.

License is GPL3 (or later). See the sourcefor details.