Skip to content


HTML5/CSS3 Zooming User Interface

I’m taking liberties with the concept of zooming user interfaces, but this is an example of something that lets you browse wikipedia by zooming in toward a link, and zooming out to go back. So I guess it’s more of a z-axis spatial visualization for history somewhat similar to what I guess Apple’s Time Machine program is like (though I have never tried it).

It uses html5′s popState and pushState to get the URL to change without reloading the page (which, btw people should use instead of the weird /#/ urls). It uses webkit transformations, which probably aren’t part of CSS3 since it’s vendor specific, but I haven’t had time to hack it to work on firefox, feel free to fork.

Zoomify

So that’s a bookmarklet. feel free to click it on this site and it’ll get rid of the infinite scrolling and for some reason it doesn’t work well on this site. Try it on wikipedia.

Posted in Design, Zooming User Interface.

Tagged with , , , , , .


BitTorrent in JavaScript with Node

A few months ago I tried to make a bittorrent client in javascript. But a few days after it started, I found out that there were already other projects with the same goal. The most complete of them was summerTorrent. However, though (I thought) it was so insanely close, it wasn’t finished. So anyway, I made a few changes that at least made basic torrenting functionality working.

summerTorrent

Posted in P2P.

Tagged with , , , , .


Chrome Extension: Desktop Search


Tango icons are purty

I felt like making some chrome extensions recently. so this is a almost totally useless one, since it uses the experimental APIs. Basically, since the new versions of chrome let you have content scripts that act off file:/// urls, you can make a script that indexes the local files and store it to a searchable index, as I have done. Plus, there’s a new omnibox api, so you can use that to search too.

Probably won’t work for anyone. but anyway, feel free to fork it on github.

Posted in Desktop Search.

Tagged with , , , , , .


Chrome Extension: Hide Element

https://chrome.google.com/extensions/detail/omjoegfimgdcgigodfpnjefanhfiagae

It’s a simple extension that uses the new chrome context menu API to gain DOM access to hide an element. It’s actually a lot more complicated than it should be since, probably chrome’s multi-process architecture makes it impossible to actually pass the DOM over, so instead you have to create a content script that listens and logs all click events and when a context menu action is triggered, you send a message to the content script which applies an action to the selected DOM node.

Anyway. Code here. http://github.com/antimatter15/hideelements

Posted in Hide Elements.

Tagged with , , .


microwave on app store

http://itunes.apple.com/us/app/microwave-google-wave-client/id386081118?mt=8

So microwave is now on the app store. Though wave was just announced to be shut down, I had the app done already (though I was waiting for a wave server update so thread continuation and attachment uploading would work), and I just published it anyway. So here it is. Grab it while wave still works :). It supports offline, so you can cache some waves and read them on-the-go.

Posted in Google Wave, Microwave.

Tagged with , , , , , , , , .


Deep Integration Wave API Sample: Blogger

http://w2embedtest.blogspot.com/2010/08/intense.html

It’s not just one post, it’s the whole blog! http://w2embedtest.blogspot.com/

Posted in Anony-bot, Deep Comment Integration.

Tagged with , , , .


1k JS 3d Function Plotter

Interestingly, it does seem that a lot of the demos for the js1k competition are a whole lot more impressive than the 10k competition. Despite that js1k started with no prizes and 10k has a collective $10,000 worth of prizes. Though I do have several entries on both. Anyway, this is the continuation of my old 3d function plotter, but that one doesn’t work anymore because i’m evil and hotlinked the  github repo and three.js updated in an api-breaking way.

Anyway, after you vote up http://10k.aneventapart.com/Entry/46 and http://10k.aneventapart.com/Entry/18 you should totally try out my 3d function plotter at http://js1k.com/demo/62

Posted in 3D, Function Plotter.

Tagged with , , , , , , , .


DOM Indexer JS Compression

There’s lots of compression systems for JS out there. There’s the really smart JS rewriter magical rhino-based ones like Closure and YUI. There’s the string-based ones, packer base62, huffman, and lz77. But of the latter category, they all rely on a sort of dictionary coder, where the dictionary (or huffman tree) needs to be sent alongside the compressed content.

Unlike strings of bits, javascript code often refers to methods on the document object model. If we were to crawl the DOM, we could get a list of DOM properties and use that as the shared dictionary which doesn’t need to be changed, sent or stored. Ever.

Example:

document.getElementById -> $dgEln

document.body.appendChild(s); -> $dbaChp(s);
And as the dictionary never needs to be stored, it’s dynamically computed based on the default browser DOM, there is a constant overhead for the indexer. The dictionary does not change size based on the size of the content.
The first prototype relied on recursively indexing properties 2-3 levels from window using the ES5 Object.getOwnPropertyNames.  That feature is only supported on IE9, Chrome 6, probably the latest versions of Safari and Firefox 4. As such, it severely limits the applicability of the algorithm.
Version two switches it to a simple for..in loop. The problem here is that it’s no loner possible to index certain things. Properties like Math, which are marked DontEnum internally can not be iterated, and thus can not be compressed (Math.cos would have been $Mac8). However, it probably makes up for this by recursively indexing things substrings of the discovered objects. So document.getElementById would be interpreted as the full document.getElementById instead of seperately compressing document and getElementById. It also uses a new hash function which makes the output more readable and the length proportional to the length of the source. length becomes $l6 document.body.removeChild becomes $dbrChp. However, this also removes the possibility of that nice fallback on things not supported by the browser. (if(document.getElementsByClassName){}else{} would have been translated as d3k2.s93k and back as document.s93k on browsers that dont support it and so browser detection gracefully degrades without blah is not defined errors).
Overall. What is the compression ratio? Not that great. If you do lots and lots of DOM access then you might get a decent ratio, but the code is slow and the ratios are relatively insignificant.

Posted in Uncategorized.

Tagged with , .


jailbreakme.com

I couldn’t resist looking into the source of it. It is obfuscated a bit, but there are some interesting parts. Example: How it detects device models.

For iPad, well there’s just one iPad so they just search the UA string for iPad and it’s totally iPad1,1. iPhone 4 is detected by the global devicePixelRatio property, because the pixel is dying. Differentiating between iPhone models (not just firmware versions) is pretty awesome. They do a speed test. Specifically, SunSpider. It’s pretty much the de-facto standard web benchmark nowadays, and it was also started by Apple for the Webkit project.

Apart from that, the exploit itself is PDF based. Which is interesting as Adobe Reader accounted for 80% of exploits in 2009. However, iOS’s implementation is probably totally independent, but it’s neat seeing this happen. The exploit is located at http://jailbreakme.com/_/device_model/device_firmware.pdf. For example, the iPhone 4′s URL would be http://jailbreakme.com/_/iPhone3,1/4.0.pdf. The resulting file is 12.9KB. I assume it’s some pretty standard attack code because I’m not a hacker and I know absolutely nothing about that.

Posted in Uncategorized.

Tagged with , , .


JavaScript <canvas> to (Animated) GIF

This is the GIF which was generated from the canvas.

This is the raw canvas element saved as a non-animated PNG

I’ve tried this before but it didn’t work. <canvas> can’t do toDataURL(‘image/gif’), and the primitive GLIF library couldn’t do much so I never had the opportunity to test my gif-merging code that I had. But I’m at it again, this time, porting it from the AS3GIF library, an awesomely comprehensive bitmap to binary gif encoder that even supports LZW compression (and the patent has luckily expired. Yay!). AS3Gif is supposed to “play and encode animated GIFs”, but since web pages can usually natively play GIFs fine, it’s only a port of the GIFEncoder portions of the library. And it works really well. The rest of this post is copied from the Github readme. Interesting how the w2_embed/anonybot embed post was a blog post turned into readme, this is a readme turned into blogpost. I’ll start with a link to the Github repo anyway:

http://github.com/antimatter15/jsgif

Basic Usage

Since it pretty much is GIFEncoder, you could consult the as3gif how-to page

But there are some differences so I’ll cover it here anyway.This is the GIF which was generated from the canvas.

You first need to include the JS files. It’s probably best if you include it in this order, but it shouldnt’ matter too much.

<script type="text/javascript" src="LZWEncoder.js"></script> <script type="text/javascript" src="NeuQuant.js"></script> <script type="text/javascript" src="GIFEncoder.js"></script> 

If you want to render the gif through an inline <img> tag or try to save to disk or send to server or anything that requires
conversion into a non-binary string form, you should probably include b64.js too.

<script type="text/javascript" src="b64.js"></script> 

Simple enough right? Now to convert stuff to GIF, you need to have a working or at least some imageData-esque array.

<canvas id="bitmap"></canvas> <script> var canvas = document.getElementById('bitmap'); var context = canvas.getContext('2d'); context.fillStyle = 'rgb(255,255,255)'; context.fillRect(0,0,canvas.width, canvas.height); //GIF can't do transparent so do white context.fillStyle = "rgb(200,0,0)"; context.fillRect (10, 10, 75, 50); //draw a little red box 

Now we need to init the GIFEncoder.

 var encoder = new GIFEncoder(); 

If you are making an animated gif, you need to add the following

 encoder.setRepeat(0); //0 -> loop forever //1+ -> loop n times then stop encoder.setDelay(500); //go to next frame every n milliseconds 

Now, you need to tell the magical thing that you’re gonna start inserting frames (even if it’s only one).

 encoder.start(); 

And for the part that took the longest to port: adding a real frame.

 encoder.addFrame(context); 

In the GIFEncoder version, it accepts a Bitmap. Well, that doesn’t exist in Javascript (natively, anyway) so instead, I use what I feel is a decent analogue: the canvas context. However, if you’re in a situation where you don’t have a real <canvas> element. That’s okay. You can set the second parameter to true and pass a imageData.data-esque array as your first argument. So in other words, you can do encoder.addFrame(fake_imageData, true) as an alternative. However, you must do an encoder.setSize(width, height); before you do any of the addFrames if you pass a imageData.data-like array. If you pass a canvas context, then that’s all okay, because it will automagically do a setSize with the canvas width/height stuff.

Now the last part is to finalize the animation and get it for display.

 encoder.finish(); var binary_gif = encoder.stream().getData() //notice this is different from the as3gif package! var data_url = 'data:image/gif;base64,'+encode64(binary_gif); 

Docs

Each of the files exposes a single global (see, at least it’s considerate!). But since there’s three files, that means that there’s three globals. But two of them are more of supporting libraries that I don’t totally understand or care about enough to document. So I’m just gonna document GIFEncoder.

new GIFEncoder() This is super parent function. You really don’t need the new keyword because It’s not really even using any special inheritance pattern. It’s a closure that does some var blah = exports.blah = function blah(){ for no good reason. Anyway, it returns an object with a bunch of methods that the section will be devoted to documenting. Note that I’ve never tested more than half of these, so good luck.

Boolean start() This writes the GIF Header and returns false if it fails.

Boolean addFrame(CanvasRenderingContext2D context) This is the magical magic behind everything. This adds a frame.

Boolean addFrame(CanvasPixelArray image, true) This is the magical magic behind everything. This adds a frame. This time you need
you pass true as the second argument and then magic strikes and it loads your canvas pixel array (which can be a real array, I dont care and I think the program has learned from my constant apathy to also not care). But note that if you do, you must first manually call
setSize which is happily defined just below this one.

void setSize(width, height) Sets the canvas size. It’s supposed to be private, but I’m exposing it anyway. Gets called automagically as the size of the first frame if you don’t do that crappy hacky imageData.data hack.

void setDelay(int milliseconds) the number of milliseconds to wait on each frame

void setDispose(int code) Sets the GIF frame disposal code for the last added frame and any subsequent frames. Default is 0 if no transparent color has been set, otherwise 2. I have no clue what this means so I just copypasted
it from the actionscript docs.

void setFrameRate(Number fps) Sets frame rate in frames per second. Equivalent to setDelay(1000/fps). I think that’s stupid.

void setQuality(int quality) Sets quality of color quantization (conversion of images to the maximum 256 colors allowed by the GIF specification). Lower values (minimum = 1) produce better colors, but slow processing significantly. 10 is the default, and produces good color mapping at reasonable speeds. Values greater than 20 do not yield significant improvements in speed. BLAH BLAH BLAH. Whatever

void setRepeat(int iter) Sets the number of times the set of GIF frames should be played. Default is 1; 0 means play indefinitely. Must be invoked before the first image is added.

void setTransparent(Number color) Sets the transparent color for the last added frame and any subsequent frames. Since all colors are subject to modification in the quantization process, the color in the final palette for each frame closest to the given color becomes the transparent color for that frame. May be set to null to indicate no transparent color.

ByteArray finish() Adds final trailer to the GIF stream, if you don’t call the finish method the GIF stream will not be valid.

String stream() Yay the only function that returns a non void/boolean. It’s the magical stream function which should have been a getter which JS does support but I didnt’ feel like making it a getter because getters are so weird and inconsistent. Like sure there’s the nice pretty get thing but I think IE9/8 doesn’t implement it because it’s non standard or something and replaced it with a hideously ugly blah blah. So Anyway, it’s a function. It returns a byteArray with three writeByte functions that you wouldn’t care about and a getData() function which returns a binary string with the GIF. There’s also a .bin attribute which contains an array with the binary stuff that I don’t care about.

WebWorkers

The process isn’t really the fastest thing ever, so you should use WebWorkers for piecing together animations more than a few frames long. You can find the rest of the WebWorkers section on the actual readme, because the rest is just a huge block of code with comments.

http://github.com/antimatter15/jsgif

Posted in Ajax Animator, Animated GIF Encoder, Multimedia Codecs, Stick Figures.

Tagged with , , , , , , , , .