Tales from a JavaScript Developer

Practicing JavaScript ninja

My Adventures Into WebGL

| Comments

So I have been pretty busy trying to get into WebGL. It is easily the best way to have a bad time in programming right now. The combination of experimental browser support, bad linux drivers, and JavaScript’s direct mapping to very old C code made it quite difficult.

I started by looking at a Learning WebGL. I 100% recommend this especially if you are unfamiliar with the domain. Why would you keep reading this if you weren’t? If you go through these lessons copy/pasting code, you will think this is simple. However, the first thing I tried was tweaking things.

Who wants a pyramid? I made a triangle cube. Who wants a cube with solid color sides? So, I made a cube with blending (gradients).

The first thing I noticed, you ever heard of perma-death games? One typo, one vertex without a color and the whole thing fails to load. There’s no 1%, 50%, or even 99% working it’s all or nothing. So, much of my time was debugging the tiniest details of my application.

One time, I spent two hours drawing and staring of my 3d object on a piece of paper. It actually didn’t help at all, the real problem was totally unrelated. I think maybe paper helps those people either with super complex or super simple problems. Mine was a problem of misunderstanding so staring at a 3d model on a 2d piece of paper did not help me.

So I will go into the most basic details here. What is WebGL and why is canvas so much better? Let’s say I want to draw a square.

I define my 4 points and tell OpenGL to go draw it. OpenGL says go fly a kite. OpenGL only understands triangles. There are two ways to do this. A triangle for every 3 vertices (gl.TRIANGLES), or one triangle, then every subsequent point forms a new triangle (gl.TRIANGLE_STRIP). Obviously, the second one is ideal as it is far more efficient on the GPU to reuse existing vertices. However, if you use the strip it will treat every new point as the foundation of the next triangle. This can cause significant problems if you want to connect vertex 3 to vertext 7 and 8. You can get some really crazy shapes that made my brain hurt looking at them.

Next post, I will start getting into the code behind Graph 3d and try to justify the few dozen hours I lost working on it.

Jodoc-js

| Comments

So it’s about time to post an update on things I’m working on lately which have been a lot, just look at my github feed: https://github.com/drewwells

Today I want to talk a bit about the documentation framework we are now using at work. It’s rather fantastic and based on a python implementation: https://github.com/davebalmer/joDoc. It hasn’t been updated at all this year, but azakus has ported the whole thing to NodeJS!

The idea is quite simple, take markdown based comments in your JavaScript file and throw them into a web page. How hard was that? No complicated syntax, no huge comment blocks to facilitate special formatting. KISS.

So!

What does this thing do, and why should you care?

First off markdown knowledge would be good to know. You have two paths here

I know markdown, but rusty on syntax Try my demo I don’t know markdown give me the Full details

Sample JavaScript file

file.js

1
2
3
4
5
6
7
8
9
10
11
/**
# file.js
Some information about the file.  The h1 above is
## main

Hey what is this, C code?
*/

function main(){
  return 'I am not C code, see ' + 5;
}

So, thanks to the /** part you will get a big h1 tag with ‘file.js’ which also acts as the index. Anywhere you link to [file.js] now links to the html page created for file.js.

There are two forms created, single file where links use hash tags to find documentation, or multi page where each html page is run through a template and an entire page with header links is provided.

Fring features: I have been adding cool features to it which can be found in ‘joapp-experiment’. I’m working with the owner to get these integrated into his repository.

File based configuration

Currently, you must maintain complicated command line scripts to use it. Why must it be so? It’s great to put these in a build tool, but sometimes you want to set it and forget it. So I have implemented via ‘require()’, Node 0.3.0+ I think, to require a separate file. This is cool, because those files can require other files say to provide a dist and a dev version of your docs <3 require().

I made a pull request for this feature on 9/8 and here it is 2 weeks later without even a comment: https://github.com/azakus/jodoc-js/pull/10. It includes a demo since I properly commented jodoeJS itself to dogfood and provide an easy demo for others. There are notes on how to use this in the README.

Serve the docs via NodeJS as a web page

It’s cool that the docs run in NodeJS b/c they are sub second fast. But why do I need to run a build command to get them going? Can’t NodeJS serve to a browser instead? The answer is Yes it can. So I wrote a small web server inside the app. It has no dependencies, so it’s very simple and dumb. I had to add proper mime-types for picky browsers like Chrome.

As the HTML is created, it is sent to the browser by hitting the URL in your browser. It can also serve the files created on disk, but way less cool. Oh did I mention, it will reparse all your source files before doing so? So, if you are actively writing documentation just hit refresh to see your changes. It couldn’t be simpler.

Testing for Optional False Params in JavaScript

| Comments

Sounds like a silly thing, but sometimes you want optional false parameters. If for nothing else than to make your parameters human readable, not just syntactically convenient.

So let’s start out:

1
2
3
4
5
var config = {
  //blur: false
};

!config.blur //Oh noes reports true

The trick here is to detect whether the variable is undefined, then for it’s truthy value. Fixed implementation:

1
2
3
4
5
6
7
8
if( config.blur != null &amp;&amp; !config.blur ){
  //Won't execute != null is false
}
config.blur = false;

if( config.blur != null &amp;&amp; !config.blur ){
  //Logic executes
}

Pretty cool huh? Test with if/else structures or you will get errors.

Github

| Comments

As someone that isn’t afraid to get his hands dirty, I find Github to be a god send. It really makes coding a dream, and it makes collaborative coding amazingly easy.

The current project I’m working on involves nearly a dozen libraries. There’s a huge difference between those on Github and those hosted else where. For one, the code hosted else where just sits in my lib directory. I make modifications to it and commit to our internal version control system (Perforce). If I want to commit those back it nearly always ends up being an arduous process of building diff files and going through a multi-week issue/communication with an author.

Now flip over to Github, let’s say there’s a minor issue with a particular feature. I open an issue and the author is notified via email. The next day that feature may get fixed. Even if it isn’t, I fork the code base and make my own. That’s how my dashboard is now almost 30 repositories full. I have no qualms getting in there and hacking away at some things. More often than not I learn 10 things for every one I bring to the table. It’s incredibly rewarding and I thank Github for this.

Github provide an amazing service to the world and the betterment of developer kind. I owe much of my working knowledge to Github committing code, reading code, and learning code from them.

My latest projects include in no particular order: Fonttest enumerates the 30+ font’s from the excellent M+ non-web fonts, I’m working on WOFFing, EOTing them via FontSquirrel. This is also my first start at Github Pages, and it is totally amazing as usual. jodoc-js This is a port from the amazing jodoc perl library. It allows standard markdown and scraping of JavaScript of files. I’m working to improve the Table of Contents building and automagic link building. I’m heavily considering starting fresh with a new repository to reduce some of the technical debt.

On a side note, don’t you wish you could EMACS the world? How many times do I ctrl+s, ctrl+b a day in the web browser and end up with some crazy shit going on :(

HP Pavilion Dv6 Quad Edition

| Comments

My new laptop is wonderful and great. It’s also completely a pos in Ubuntu. Number one problem is the brightness level in Linux, it’s always 100% and it can’t be modified by the keyboard, or even /sys properties. However, the magical xrandr can fix it.

In integrated graphics mode: use xrandr as so

1
xrandr --output LVDS1 --brightness 0.4

I made a script to use make this a little more automated:

1
xrandr --output LVDS1 --brightness $1

Save it to brightness.sh (no sudo required on my system).

1
./brightness.sh 0.7

Leaflet

| Comments

This is just a quick post, I’m working on putting together a demo using Leaflet. I’m curious if it has the necessary features to port Craigmaps to it, then I will finally have something that runs on mobile devices and can find a new place to live on the go! Anyways, quick demo here

SyntaxHighlighter Evolved Is Broken

| Comments

I apologize all of the code of my posts now is completely unformatted and missing syntax highlighting. I have looked into the problem numerous times, and fixed it numerous times. It usually involves removing and re-adding the plugin or doing other things. I am now very annoyed there has been no update to the reason syntax highlighter will stop working after a few days, weeks.

I am looking for a new one, preferably one that will not break every couple of days. I will have to go back through all of my posts and update the syntax to this new highlighter.

Don’t use this plugin: SyntaxHighlighter Evolved

Craigmaps

| Comments

Quick post, I finally got Craigmaps generally stable. It’s a huge series of ajax calls on average 150. This could use some fine tuning or caching. Try it out Craigmaps

Better Know JavaScript - Google Static Map

| Comments

I’ve decided to start exploring JavaScript –not frameworks ontop of JavaScript– in order to better understand what I use but do not understand. First candidate: Creating-map-previews-with-jQuery-and-Googles-Static-Map-API

My job is not to directly emulate what is going on in Ray’s Post, but to explore ways to do this in just JavaScript no pesky script tags above your raw code. The only tricky part is tracking onkeyup, I refer to http://www.quirksmode.org/js/keys.htmlfor browser compliance.

Here she goes!

1
2
3
<textarea cols="30" rows="2" id="address">Type address here</textarea>
<br/>
<img width="400" height="400" title="Map!" id="map" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(function(){
var base = "http://maps.google.com/maps/api/staticmap?zoom=12" +
    "&size=400x400&maptype=roadmap&sensor=false&center=",
    map = document.getElementById("map"),
    area = document.getElementById("address"),
    virgin = true;

area.onfocus = function(ev){
  if( virgin ){  //Touched for the very first time?
    virgin = false;
    this.value = '';
  }
}
area.onkeyup = function(ev){
  //All sorts of broken things with detecting keycodes,
  //I'm just looking for value
  map.src = this.value.length > 4 ? base + escape(this.value) : '';
}
})();

However, seeing is believing

This should work in all browsers, I don’t have Windows to test this though :)

NodeJS Proxy to Simplify IWS API

| Comments

Normally I learn a new platform by painfully doing some file operations in that language. This is a good way to find out about some of the languages ability to provide synatic sugar atop bad APIs, but a poor way to explore the language.

Fortunately, I found a great use for node js. Our corporate server technology is very behind on REST. So I wanted to build a proxy server to convert their API into a RESTful or as RESTful as possible API.

First step was finding a way to create a HTTP proxy. This can be done with 20 lines of code in Node JS. However, this is pretty ghetto and I want to do this with a nice API and just one line of code, something like proxy( port, domain, request, response ).

I found just that here: https://github.com/nodejitsu/node-http-proxy.

Now, let’s look at some code

1
2
3
4
5
6
7
8
var express = require('express'),
     app = express.createServer(),
     httpProxy = require('http-proxy');

app.get("/iws/*",function(req,res){
    var proxy = new httpProxy.HttpProxy(req,res);
   proxy.proxyRequest(80, 'iws.erdas.com', req, res);
});

This will look for requests on /iws/, I’m using express for easier routing, then proxy those to iws.erdas.com. The requests are automatically sent back to the user.

This isn’t what I set out to do. I wanted to simplify the API, so I looked over at ARCGIS REST services and went from there.

So, I will be taking this:

http://iws.erdas.com/ImageX/imagex.dll?image?cache=true&transparent=true
&fill=ffffff&quality=60&type=jpg&l=2&tx=2&ty=1&ts=256&
layers=/sampleiws/images/geodetic/usademo.ecw&srs=EPSG:4326

and turning it into this:

http://localhost:3000/iws/map/sampleiws/images/geodetic/usademo.ecw/2/2/1/

Now the how:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
app.get(/^\/iws\/map\/?([^?]+)?(.+)?/, function(req,res){
    var proxy = new httpProxy.HttpProxy(req, res),
  captures = req.url.match( /^\/iws\/map\/?([^?]+)?(.+)?/ ),
        layer = ( captures && captures.length > 1 && '/' + captures[1] ) || '',  //bug requires prependend /
  qstring = '',
  tile = [];

    if( /\/\d+\/\d+\/\d+\//.test(layer) ) {

  layer = layer.replace(/\/\d+\/\d+\/\d+\//,function(substr, offset){

      tile = substr.match(/\d+/g);
      return substr.slice( offset, substr.length );
  });

  qstring = ['&l=',
         tile[0],
         '&tx=',
         tile[1],
         '&ty=',
         tile[2],
         '&type=jpg',
         '&fill=ffffff',
         '&transparent=true',
         '&cache=true',
         '&quality=60',
         '&ts=256',
         '&srs=EPSG:4326'
        ].join('');

    } else if( captures && captures.length > 3 ){

  console.log( 'QString: ' );
  //Test qString for url parameters, otherwise we need tile nouns to find the map tile
  qstring = captures[2];


    } else {

  //Fail, what to do
    }

    //get http://iws.erdas.com/ImageX/imagex.dll?image?cache=true&transparent=true&fill=ffffff&quality=60&type=jpg&l=2&tx=2&ty=1&ts=256&layers=/sampleiws/images/geodetic/usademo.ecw&srs=EPSG:4326
    req.url = '/ImageX/imagex.dll?image?layers=' + layer + qstring;
    console.log( req.url );
    proxy.proxyRequest(80, 'iws.erdas.com', req, res);

});

app.listen(3000);

QED