Tuesday, May 29, 2012

choking on cookies

Just a note: if you are designing an integration using iframes (like where your content shows up in an iframe on some other domain's site) you need to be aware of some pretty deep browser-specific issues involving cookies. IE will block cookies until some privacy blahblah is set; Safari has similar issues, but it's issue is about cookies on pages that haven't been directly navigated to (i.e. they've only shown up in an iframe, rather than the domain having ever been seen in the URL bar.)

There might be some further differences between the two cases; it seems like IE will allow cookies over the life of the page, at least, which is more than we got from Safari (which was a big issue because our pattern was to authenticate in one endpoint call, and then do further requests for more data) but don't quote me on that. The short of it is: you have to do a lot more QA on cross-brower issues if they involve iframes and other sites, and in fact the problem are so significant you should be thinking about them as you architect your embedded pages (and possibly doing rapid prototypes to make sure you can get to the cookies you need to when you need them.)

Wednesday, May 23, 2012

got python? you got a webserver...

At Peter Cooper's How to Build a Chat Room in JavaScript in Under an Hour webinar I learned this trick: if you have python installed on your system (many OSX machines do by default), you have a cheap-and-cheerful, ready-to-go web content server:
Just go to the relevant directory and type:

python -m SimpleHTTPServer 8081

or whatever port you want, and you can then go to http://localhost:8081/
(Slightly longer explanation at the Linux Journal.)

This can be especially user because some browsers are a bit weird about loading stuff from the file system, you run into odd cross-site-scripting style issues, like if you try to load a static ".json" file or what not.

By the way Peter Cooper also runs Javascript Weekly, a roundup of JavaScript news and articles. Great to finally have found a way to keep up with neat stuff in the industry...

UPDATE:
There's a variant if you want to run scripts:


python -m CGIHTTPServer 8081

It's pretty old-school; you make a cgi-bin directory under where you will run the command. Your scripts then have to start with #!/usr/bin/php or whatever, and have execute permissions.

Also I just realized (duh) that PHP has its own webserver-


 php -S localhost:8000

Which avoids some pesky header issues when I was trying to run through Python CGI.

UPDATE UPDATE
I was running into CORS problems running my own dev server ("Access-Control-Allow-Origin" issues). The python based solutions I googled up looked annoying, but here's another basic webserver you can use, with an argument that runs around the CORS issues: 

npx http-server . -p 9999 --cors='*'

(Obviously pick your own port)

UPDATE UPDATE UPDATE

 
UPDATE UPDATE UPDATE UPDATE

Oddly missing from that previously linked list (tho mentioned in a comment:

npx serve@latest

Thursday, May 17, 2012

the way the cookie crumbles


Today as a quick tool to help with some QA I made cookiemonster, a simple tool to go through all the cookies associated with the request and print out the cookie content.

Clearly not rocket surgery, but useful today! If you view the source of that file, you can see a little bit of odd JSON parse and stringify. We sometimes stuff JSON structures as cookies (a cheap and cheerful technique but you need to be aware that those cookies then get sent with every request for all non-CDN'd content - so don't overdo it!) and it's nice to use stringify's ability to format the content-- but a barse JSON parse and stringify would thrown exceptions for non-JSON'd data, so I catch that case and just treat it as a plain string.

slashmaze


slashmaze - source (click to redraw)

Our marketing director Gerard LaFond pointed me to an upcoming book by his co-collaborator (and Serious Games superstar) Ian Bogost... the books is called 10 PRINT CHR$(205.5+RND(1)); : GOTO 10 and that happens to be a working program for the Commodore 64 that generates a pattern very much like you see here.

I want to reiterate, processing.js is a fun tool for stuff like this (despite the lack of IE support) and http://sketchpad.cc/ is one of the easier ways of getting something up and running in a hurry.

I'm looking forward to the book! Should be a good read.

Friday, May 11, 2012

it's pronounced 'wolfen-STEEN'

So Bethesda released a playable online port of the 1992 PC classic Wolfenstein 3D - it was a great game with awesome music, the first FPS worthy of the name, and the precursor to DOOM. When Peter Cooper's JavaScript Weekly (kind of a must-read for keeping up with the whole HTML5/js/jQuery world) linked to it they mentioned
 Interestingly, it doesn't use Canvas, etc, but a lot of CSS and DOM manipulation.
So I took a peek with Firebug, and wow, they're right! I always wondered if you could build a game this way, and sure enough! (It's a testimonial to the cleverness of the original Wolf3D programmer John Carmack, how robust his ideas in rendering engines were). When you inspect the DOM, you can see that besides some divs for "ceiling" "floor" and "player-weapon" and the like, there's a giant pile of (mostly hidden) sprite divs, and the a big collection 3 pixel wide vertical slices. Each one of those then holds a carefully manipulated piece of a wall texture. There's a lot of manipulation of the z-index to get everything to appear in the right order as well. (the Wikiepedia article talks a bit about this technique, called "Ray Casting".

Quite the tour de force! I've seen recreations of the basic technique in minimalist programming competitions, but it's cool to see my old friend Wolf3D.

Here's one of the sprite sheets from it, the basic soldier...

At first I was going to slice this by hand to fit in this site (the original file is a horizontal row 3136 pixels across), but then I realized I could just use some CSS shuffling. (In theory I could have then baked the result into a single image, but but it was a a bit more fun this way)

And check out this cool walk through with Wolf3D creator John Carmack!

Monday, May 7, 2012

lose dozens of Mbs just by following this one weird old tip!

The other week the Apple Blog Daring Fireball linked to an adactio blog entry about how after a number of years of forgetting about dialup users and focusing on folks blessed with broadband (which, conveniently, is an experience closer to what the developers themselves enjoy on their desktops) "mobile" is making a whole host of old concepts in bandwidth and loading efficiency relevant once more.

My company Alleyoop recently had a sprint dedicated to improving site/app performance but we missed one obvious thing: optimizing our images. Those aforementioned links recommended a specific tool: ImageOptim. I heartily concur; using this is a total no-brainer. (Unfortunately it's OSX only and I tend to code on PCs... I think some of the several format-specific tools it frontends are available on different platforms, but as far as I know only Macs boast this "one stop shopping" aspect.)

Not being the trusting type, I copied a large folder of images as a test, made a backup copy, and let ImageOptim do its thing. (ImageOptim is great at updating images "in place", including spidering through subfolders and ignoring non-image files, though its multi-tool approach makes it a bit slow). I then made a script to make an HTML doc with the original and the optimized version of each image side by side, and invited our designer to take a peek at the result. The visual differences between the images were negligible (the most suspicious thing was some very, very faint color shifting on some PNGs) but the byte savings was immense: the 3.2 meg contents of the folder smushed down to about 1.6 megs. 

Here's the quick and exceedingly dirty Perl script I concocted to do the A/B test, it reads all the files in "files.txt", and then shows that file in the directory before/ next to that file under after/ . The files are sorted by decreasing order of bytes saved, and a little additional savings information is printed up as well.

print "<center><div style='width:3000px'><nobr>";
open(FILES,"files.txt");
while(defined($line=<FILES>)){
  chomp $line;
  push (@files,$line);
  $sizediff{$line} = (-s "before/$line") - (-s "after/$line");
  $sizepercentdiff{$line} = (100 * (-s "after/$line")) / (-s "before/$line");
  $totalsave += $sizediff{$line};
  $totalpercent += $sizepercentdiff{$line};
  $totalpercentCount += 1;


}
close FILES;


@sortfiles = @files; #sort numSort @files;
foreach $line (sort{$sizediff{$b} <=> $sizediff{$a}} @sortfiles){
  print "$line ".int(($sizediff{$line}/1000)+.5)."Kb Diff  (".int($sizepercentdiff{$line}+.5)."%)<br>";
  print "<img src='before/$line'><img src='after/$line'><br><br>\n";
}
print "TOTAL SAVED: ".int(($totalsave /1000)+ .5)."Kb AVG PERCENT: ".int(($totalpercent/ $totalpercentCount )+.5);
print "</nobr></div></center>";

(PROTIP: to get the bare list of files this program uses on windows, "dir /b > files.txt" is just the thing.)

Man, I used to love Perl so much, and it still shows its utility in every job I've had since graduation, but my street Perl from the mid-90s is showing it's age, I never really absorbed its object model, and its API can be so barebones... (plus on the cheap webspace I rent, it never seems to have the useful modules I want already installed...)

Tuesday, May 1, 2012

a juicier filter

Here is a small proof-of-concept I came up with for work, a way of letting students type in part of what they're studying and letting them choose from matching topics.

In the box type something  like "solving", and then maybe "solving mul", and see what happens...


The problem this tries to solve is making searching and filtering a bit more interesting and "juicy". There's a bigger UX problem about whether it's better to have kids type in the subject they're looking for help with, or to start by choosing from a list of 9 or 12 topics and starting from there. My gut is that the former is a more useful concept (at least until we're able to provide "show us which textbook you're using" anyway), and that is backed up by how students tended to type in the topic they were interested in when one of our user surveys asked them "What were you looking for when you came to the site?"

In thinking what it would take to turn this into a "real" widget... currently it lacks discoverability, a student might not know what kind of keywords would give useful results. I might suggest having random topic tiles slowly floating in and out of the tile area when the page first loads, giving a hint of the kind of thing the student might then type into the search box. Also there should be a clearer "no results found" message, along with more sophisticated word matching (matching across various verb tenses and plurals etc, instead of the simplistic string prefix matching shown here.)

You can go to the page and view source to see how it's done. Besides some fun with easing and animation (including tile resue, which both limits the amount of DOM objects that have to be generated and sometimes has cool "reshuffling" of existing tiles), this is a decent example of using Ben Alman's debounce jQuery plugin. Debounce (and its cousin "Throttle") is a tool that should be in every jQuery developer's toolbox... what it does is allows you to pile up upates in front of expensive procedures, so in my case rather than having every keypress launch tiles (which would end up with a messy pile of chained or interrupting animations) it waits until the user has stopped typing for a short time.

So instead of writing
$('.filter').keyup(updateStage);
I wrote
$('.filter').keyup( $.debounce( 500, updateStage ));

which put in a delay of 500 millis before trying to reapply the filter and relaunching the animation.

Good stuff! You can use it for keypresses or inside of a UI widget, like a slider control. It's epecially useful for making sure you don't go off firing a multitude of Ajax calls. (I first learned about this at the jQuery Boston meetup group in a presentation by Brian Del Vecchio)

simbiozo and the art of the startup weekend

This weekend I was a part of the Boston EDU Startup weekend. You can read some great coverage of the event at BostonInno. The shape of the 48 hour (they kept calling it 54 hour, oddly) event was people pitching concepts for education startups, teams forming around 7 or 8 of those ideas, and then hours and hours of putting together mockups and prototypes, doing market research, and preparing pitches to be delivered in front of a panel of judges the final evening.

My team was "Simbiozo" (the Esperanto word for symbiosis). The concept morphed into an app like "Word with Friends" or "Draw Something" but instead of playing Scrabble or Pictionary you're collaboratively captioning panels from a comic strip with someone with compatible language practice aspirations (for example, maybe you speak English and have just a bit of Spanish you'd like to polish: the app would team you with a Spanish speaker who is looking to do likewise in English.)  Here is a screenshot of the live landing page we made:


The judges seemed to like our concept and were impressed by our presentation, but we ended up not placing. Still, it was a fun weekend, and here are some lessons I took from it:
  • I need to ramp up my go-to-server-language mojo for projects like this-- the Perl CGI on cheap webhosting that has served me well for the last decade and a half is showing its age, and can't easily provide a good backend to the kind of AJAX-based frontend I love to do. PHP, though, shows  promise for filling this gap (at least until I get my act together and can do a node.js site from scratch on something like heroku...)
  • The teams that won were either an idea the teamlead has been working on for a while (and had a working demo for,) or a simple idea on a team full of techies. In either case, I think the "live demo" - even if fakey - goes far in impressing the judges, even more than the detailed customer research that our mentors were saying was the key.
  • I did this the weekend after a 48-hour-game-jam weekend. That was probably a mistake.
So, I still get the impression that I'm not much of an entrepreneur, but I do like supporting entrepreneurs in their ideas. I was fortunate in finding a good team (having the great designer I work with at Alleyoop was a godsend) and I think I helped suggest a single, solid idea, vs the original pitch was was more vague. So despite the failure of the dabblers to make a dent against the people who have been grinding their idea for a while, it was still a solid experience.