rolando.cl
Compiling JavaScriptCore for iOS
While for some time now you’ve been able to add your own version of JSC to your iOS projects, there’s still no painless solution to compile the svn version yourself. So here are my steps in order to get that working:
- Duplicate target (rename iOSJavaScriptCore or something appropiate)
- manually edit the xcode project (the xml file) and change the target product type to com.apple.product-type.library.static
- Link to proper iOS libraries (the same libraries, but point them to the iOS SDK)
- remove “other linker flags”
- Deal with the derived sources problems, for the script-generated .lut.h files. The way I did it was to manually add the include search path to the place where the files where being generated. This is by far not the best solution but it works. [EDIT] Another way pointed in the same thread is to copy the Derived Sources script phases on the iOSJavaScriptCore target and make those the first phases to be run. Make sure you eliminate the dependencies after adding those phases.
I hope that helps some other iOS developers out there.
Future post: how to actually use JSC for scripting and some pointers along the way.
Btw, if someone has something similar to this list but for building JSC for android, please let me know :)
Comments removed
I just cleaned up the site, I removed all the comments and finally added captcha to try to minimize the spam bots (let’s see how long that takes)
Naive fallback to canvas
Disclaimer
Falling back to canvas should be used only when your game is really simple and has no fancy shader. It can also be used to provide the player with a subset of the experience of your game, for instance for mobile devices, when there’s no WebGL support. So what I’ll descrive here only works for really simple games and perhaps, to just show a limited experience instead of a “download Chrome to play this game”
The theory and implementation
When writing ChesterGL I realized that if I kept the rendering logic isolated enough, I could easily create a thin layer for adding new rendering techniques, like Canvas API or plain DOM. The rationale behind is that all the math is done in a very general way (using the good old matrix transformations), so I just needed to think through it. One thing that makes things easier, is that for every image (sprite) rendered on screen, you don’t really need to position the image, just set the transform of the current context before drawing and that’s it. And of course, you can easily get the transform from the current model-view matrix:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
ChesterGL.Block.prototype.render = function () { if (ChesterGL.webglMode) { // ... the usual WebGL way } else { var gl = ChesterGL.offContext; // canvas drawing api - we only draw textures if (this.program == ChesterGL.Block.PROGRAM.TEXTURE) { var m = this.mvMatrix; var texture = ChesterGL.getAsset('texture', this.texture); gl.globalAlpha = this.opacity; gl.setTransform(m[0], m[1], m[4], m[5], m[12], m[13]); var w = this.contentSize[0], h = this.contentSize[1]; var frame = this.frame; gl.drawImage(texture, frame[0], texture.height - (frame[1] + h), frame[2], frame[3], -w/2, -h/2, w, h); } } } |
I added an option to set the opacity of the sprite as well by changing the state of the context before drawing. If you look at the drawImage call, we can even support sprite sheets very easily. So with only a few lines, you can support WebGL sprites as well as pure canvas API sprites. Since we use the same matrix for WebGL and canvas, the whole scene graph is preserved so everything else works the same way.
So where should you start this? I did it in the initialization code, where you create the WebGL context from the canvas, if that fails, then create a 2d context:
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 |
/** * tryies to init the graphics stuff: * 1st attempt: webgl * fallback: canvas */ ChesterGL.initGraphics = function (canvas) { try { this.canvas = canvas; if (this.webglMode) { this.gl = canvas.getContext("experimental-webgl"); } } catch (e) { console.log("ERROR: " + e); } if (!this.gl) { // fallback to canvas API (can use an offscreen buffer) this.gl = canvas.getContext("2d"); if (this.usesOffscreenBuffer) { this.offCanvas = document.createElement('canvas'); this.offCanvas.width = canvas.width; this.offCanvas.height = canvas.height; this.offContext = this.offCanvas.getContext("2d"); this.offContext.viewportWidth = canvas.width; this.offContext.viewportHeight = canvas.height; this['offContext'] = this.offContext; this.offContext['viewportWidth'] = this.offContext.viewportWidth; this.offContext['viewportHeight'] = this.offContext.viewportHeight; } else { this.offContext = this.gl; } if (!this.gl || !this.offContext) { throw "Error initializing graphic context!"; } this.webglMode = false; } this['gl'] = this.gl; // get real width and height this.gl.viewportWidth = canvas.width; this.gl.viewportHeight = canvas.height; this.gl['viewportWidth'] = this.gl.viewportWidth; this.gl['viewportHeight'] = this.gl.viewportHeight; } |
There are some things that will not work, the most obvious being batched sprites (BlockGroup in ChesterGL) and shaders. But if you want to have a very simple fallback line, this could work.
For clearing the screen, you have two options: either clear the whole rect, or paint it some color. I opted for drawing a black rectangle to simulate the glClear in WebGL:
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 |
/** * main draw function, will call the root block */ ChesterGL.drawScene = function () { if (this.webglMode) { // WebGL draw mode here } else { var gl = this.offContext; gl.setTransform(1, 0, 0, 1, 0, 0); gl.fillRect(0, 0, gl.viewportWidth, gl.viewportHeight); } // start mayhem if (this.rootBlock) { this.rootBlock.visit(); } if (!this.webglMode) { // copy back the off context (if we use one) if (this.usesOffscreenBuffer) { this.gl.fillRect(0, 0, gl.viewportWidth, gl.viewportHeight); this.gl.drawImage(this.offCanvas, 0, 0); } } } |
I even let the option there to use an offscreen buffer for drawing (something like double buffering). I did some quick performance test and I couldn’t find a big difference between using fillRect instead of clear. Also, we need to set the transform to the unit matrix.
Conclusion
It can be very trivial to have a simple fallback to canvas API, but you must keep in mind what you will use it for. One concern would be performance: it is definitively not bad, but it’s not as good as it can be with WebGL, also you will lose all the cool things you would be able to do in WebGL, like adding 3D objects to your 2d game, 3D effects/transitions or fancy shaders.
One way to optimize the canvas API rendering would be to do not draw the whole screen and use just dirty rects to only draw the things that where modified. Another optimization would be to port BlockGroup (batched sprites) and draw those sprites to an offscreen buffer, this would work great for tiled maps or backgrounds.
That’s it… easy and simple fallback to canvas API when WebGL is now available for your game. Oh, and it also works on iOS! I got ~26fps with 12 moving sprites on iOS 4.3.5 and ~35fps with 42 moving sprites on iOS 5 – pretty good for canvas!
If you want to try this technique, you’re more than welcome to download ChesterGL or fork it from github (but please note that ChesterGL is still a work in progress that I maintain on my free time). If you’re also interested, you can read the original article where I introduced ChesterGL.
Note This article is a re-post of the one posted on AltDevBlogADay, you might want to check the original article
Meet Chester, my dog
Meet Chester
Chester is my dog. He’s sloppy and messy, but most of the time, let’s say 80% of the time he’s the best dog in the world PERIOD.
The other that I asked him: “Hey Chester, would you mind teaching me some WebGL? I understand you’ve been playing a lot with it, and you even made some cool WebGL demo”, and since he’s such a good dog he had no problem in teaching me.
First, the first
Chester is a good dog, but he’s not a good teacher, and he has little patience, so he told me: “if you want to learn webgl, just go to learning webgl and when you finish with the lessons, come back for some really premium extra knwoledge”.
After reading the lessons, Chester asked me: “hey, what about we go through the basics? – and while we’re on it, let’s take a look on how we can create some cool 2d thingy using webgl, and maybe with a graceful fallback to canvas.”
And so we did. These are the basics.
1) WebGL == OpenGL-ES 2.0
Don’t know OpenGL? what about OpenGL-ES 2.0? if not, go read some books. If you’re lazy, the webgl lessons are good enough for starters.
2) Let’s take you to the matrices
When it comes down to WebGL, it’s all about your matrices, you have the projection matrix, the model-view matrix and some other matrices.
But what are the 3d matrices? Here’s where your linear algebra classes must be remembered. For us they’re going to be basically transformation matrices. 3D ones. So you use them to store your model transformations: translate, rotate, scale. In order to concatenate two transformations, you would just multiply them and the result is the concatenation.
In order to understand a little bit more about this, Chester brought up the next example: let’s create a simple scene graph, you know, like the one used in a very well known 2d game engine cocos2d.
The scene graph is what holds the objects in your game scene and how you would traverse them. The basic structure we’re going to use is a block (like a construction block) and every block can contain other blocks. Blocks transformation should be relative to it’s parent, like so:

In this example, the big block (a 64px square) is the parent and the small one (a 32px square) is the child. The big block is positionated at the middle of the canvas, and the little one has a relative position of {32,0}. Since 32 is half the width of the parent, the center of the child is exactly on the right side.
Ok, let’s have some fun, first let’s move the little one outside the bounds of the block, so if we set its position to {32 + 16, 0}, it should be right outside:

Cool. Now let’s rotate the bock 45 degrees:

Even cooler :) – What would happen if we rotate the parent in -45 degrees?

And that’s how our concatenated transformations should work: the child transformation (so far, rotation → translation) should be concatenated to the one from the parent. The first 3 examples were just a single translation, but after that, we added the rotation, and since we rotated the parent in -45 degrees, it looks like if our little block is not rotated.
Fun fun. But enough for now said Chester, we need to move on.
3) It’s all about 2D
We’re going to use WebGL, a 3D engine to do some cool and performant 2D graphics, like 2D sprites and 2D games. So Chester said “When doing 2D we face a completely different challenge: you will not be filling the screen with thousands of triangles, you will be sending lots of textures to the screen, so your bottleneck will be the fill rate instead of how many triangles you want to draw. The fill rate is how fast you can send the texture — usually a much higher quality texture than in a 3D game — and how many of them you can use at the same time in the screen”. Then, after a small break playing with the ball, Chester continued “The thing is, to achieve what we want, we will be fixing a coordinate, in this case z = 0, to draw everything in a plane. Thus, our sprites will be represented by two triangles forming a square and that square is the constructing block we talked about earlier.”
Show me the code!
I was getting a little bit bored with too much talking and no coding, so I demanded Chester to show me the code. He said “ok, but I will just give you the hints, you can build up from there and make sure you refer to the webgl lessons when you feel lost”.
And so, Chester continued “The first thing we will do, is to set our projection. The projection we’re looking for must be a 3D, but must look 1-1 with the pixel size of the canvas we’re drawing into, right?”. And then he started typing.
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 |
setupPerspective: function () { var gl = this.gl; gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clearDepth(1.0); var width = gl.viewportWidth; var height = gl.viewportHeight; gl.viewport(0, 0, width, height); this.pMatrix = mat4.create(); if (this.projection == "2d") { // 2d projection console.log("setting up 2d projection (" + width + "," + height + ")"); mat4.ortho(0, width, 0, height, -1024, 1024, this.pMatrix); } else if (this.projection == "3d") { // 3d projection console.log("setting up 3d projection (" + width + "," + height + ")"); var matA = mat4.perspective(60, width / height, 0.5, 1500.0, matA); var f_aspect = (1.7320508075688776 / (width / height)); var zeye = height / f_aspect; var eye = vec3.create([width/2, height/2, zeye]); var center = vec3.create([width/2, height/2, 0]); var up = vec3.create([0, 1, 0]); var matB = mat4.lookAt(eye, center, up); mat4.multiply(matA, matB, this.pMatrix); } else { throw "Invalid projection: " + this.projection; } }, |
NOTE: “for now, think of this as a magic object that holds some important information. We will be building around it and with time, you will understand”, Chester said.
The first thing that I asked after reading the code was “Wait! what’s that weird hardcoded number!?”. And Chester told me what it was:
“It’s the cotangent of half the field of view, which we’re hardcoding to 60 degrees. We use that to calculate f / aspect_ratio in order to get the proper zeye of the camera. That gives us a 1-1 relation between rendered points and pixels”. Pretty cool, I thought.
And then Chester started to discuss the “3d” proyection.
“So, you first create a simple projection matrix, with a fov of 60 degrees, with the right aspect ratio, znear of 0.5 and zfar of 1500, and store that in matA. After that, we calculate the parameters for the lookAt, which are the zeye previously discussed, the eye, center and up vectors. We pack all those into matrix B, and concatenate those transformations in the pMatrix, the projection Matrix.”1
So, how do I render a sprite? I asked Chester, and so Chester answered.
“What is a sprite? I already told you a sprite is two triangles, but how are they represented in the webgl world? Let’s see what we need first.”
1 2 3 4 5 6 7 8 9 |
/** * @type {?WebGLBuffer} */ glBuffer: null, /** * @type {Float32Array} */ glBufferData: null, |
That’s all? I asked, what about the buffer for color, position and textures? (remembering the lessons in webgl). And Chester told me that we could pack all those in a single array, a technique known as “interleaved array”. That sounded cool, so I asked him more about that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/** * this is the size of the buffer data (Float32Array) * @const */ Block.QUAD_SIZE = 36; Block.create = function (rect) { var b = new Block(); if (rect) { b.setFrame(rect); } // set default color b.setColor(1, 1, 1, 1); var gl = ChesterGL.gl; // just a single buffer for all data (a "quad") b.glBuffer = gl.createBuffer(); b.glBufferData = new Float32Array(Block.QUAD_SIZE); // always create the mvMatrix b.mvMatrix = mat4.create(); mat4.identity(b.mvMatrix); return b; } |
Why 36? I know what a “quad” is (frame + texture + colors), but why 36?
1 2 3 4 |
36 == 12 + 8 + 16 12 == 3 * 4 // 4 points for the frame, 3 coords each (x, y, z) 8 == 4 * 2 // 4 points for the tex coord, 2 coords each (u,v) 16 == 4 * 4 // 4 colors, one for each point in the frame, 4 coords each (r, g, b, a) |
Ok, that makes sense. But how do we send the data to the GPU?
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 |
render: function () { var gl = ChesterGL.gl; // select current shader var program = ChesterGL.selectProgram(Block.PROGRAM_NAME[this.program]); gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer); var texOff = 12 * 4, colorOff = texOff + 8 * 4; gl.vertexAttribPointer(program.attribs['vertexPositionAttribute'], 3, gl.FLOAT, false, 0, 0); gl.vertexAttribPointer(program.attribs['vertexColorAttribute'], 4, gl.FLOAT, false, 0, colorOff); gl.uniform1f(program.opacityUniform, this.opacity); var texture = ChesterGL.getAsset('texture', this.texture); // pass the texture attributes gl.vertexAttribPointer(program.attribs['textureCoordAttribute'], 2, gl.FLOAT, false, 0, texOff); gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, texture.tex); gl.uniform1i(program.samplerUniform, 0); // set the matrix uniform (actually, only the model view matrix) gl.uniformMatrix4fv(program.mvMatrixUniform, false, this.mvMatrix); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } |
All right! now we’re talking. I could see that Chester was using the well known vertexAttribPointer, but just one bind and setting the offset of the call to match the position of the array. He’s also multiplying the offset by 4 because a Float32Array contains 4 bytes. Clever dog! Then I gave him a treat. He was happy.
Chester then showed me the shader and it was nothing out of the ordinary, just a very simple texture shader. So I asked him “Ok, but how do I fill the bufferData?”
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 51 52 53 54 55 56 57 58 59 |
transform: function () { var gl = ChesterGL.gl; var transformDirty = (this.isTransformDirty || (this.parent && this.parent.isTransformDirty)); if (transformDirty) { mat4.identity(this.mvMatrix); mat4.translate(this.mvMatrix, [this.position.x, this.position.y, this.position.z]); mat4.rotate(this.mvMatrix, this.rotation, [0, 0, 1]); mat4.scale(this.mvMatrix, [this.scale, this.scale, 1]); // concat with parent's transform var ptransform = (this.parent ? this.parent.mvMatrix : null); if (ptransform) { mat4.multiply(ptransform, this.mvMatrix, this.mvMatrix); } } var bufferData = this.glBufferData; if (this.isFrameDirty || this.isColorDirty) { gl.bindBuffer(gl.ARRAY_BUFFER, this.glBuffer); } if (this.isFrameDirty) { // NOTE // the tex coords and the frame coords need to match. Otherwise you get a distorted image var hw = this.contentSize.w / 2.0, hh = this.contentSize.h / 2.0; var _idx = 0; var z = this.position.z; bufferData[_idx+0] = -hw; bufferData[_idx+ 1] = -hh; bufferData[_idx+ 2] = 0; bufferData[_idx+3] = -hw; bufferData[_idx+ 4] = hh; bufferData[_idx+ 5] = 0; bufferData[_idx+6] = hw; bufferData[_idx+ 7] = -hh; bufferData[_idx+ 8] = 0; bufferData[_idx+9] = hw; bufferData[_idx+10] = hh; bufferData[_idx+11] = 0; var tex = ChesterGL.getAsset("texture", this.texture); var texW = tex.width, texH = tex.height; var l = this.frame.l / texW, t = this.frame.t / texH, w = this.frame.w / texW, h = this.frame.h / texH; _idx = 12 + this.baseBufferIndex * Block.QUAD_SIZE; bufferData[_idx+0] = l ; bufferData[_idx+1] = t; bufferData[_idx+2] = l ; bufferData[_idx+3] = t+h; bufferData[_idx+4] = l+w; bufferData[_idx+5] = t; bufferData[_idx+6] = l+w; bufferData[_idx+7] = t+h; } if (this.isColorDirty) { _idx = 20 + this.baseBufferIndex * Block.QUAD_SIZE; var color = this.color; for (var i=0; i < 4; i++) { bufferData[_idx+i*4 ] = color.r; bufferData[_idx+i*4 + 1] = color.g; bufferData[_idx+i*4 + 2] = color.b; bufferData[_idx+i*4 + 3] = color.a; } } if (this.isFrameDirty || this.isColorDirty) { gl.bufferData(gl.ARRAY_BUFFER, this.glBufferData, gl.STATIC_DRAW); } }, |
In a step by step:
- If the transform is dirty (that is, if we moved the block, rotated or scaled it), after that we need to recalculate the transform. Also, if our parent’s transformation is dirty, we also need to recalculate it.
- To transform, first load the identity, second translate, then rotate, and finally scale. The order is very important! Lastly, if we have a parent transformation, we must concatenate it with the one of the current block.
- When the transform is ready, it’s time to fill the buffer data:
- If the frame is dirty, copy the right coordinates on the vertex first to form the two triangles: bottom left, up left, bottom right for the first one, and the last two + top right for the second triangle. The same thing goes for the texture, but without z.
- The color is easy: just copy the current color on the four vertices.
- As a final step, send the buffer data to the webgl buffer.
Seems pretty easy. Chester pointed out that having the Float32Array created just once and copying the data only when it has changed makes a huge performance improvement.
At this point I had only one question left: How do you start the whole thing? I mean, how do you start the rendering chain?
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 |
/** * main draw function, will call the root block * (this is in ChesterGL) */ drawScene: function () { var gl = this.gl; gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // global blending options gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); gl.enable(gl.BLEND); // start mayhem if (this.rootBlock) { this.rootBlock.visit(); } } // this is in a Block visit: function () { if (!this.visible) { return; } this.transform(); var children = this.children; var len = children.length; for (var i=0; i < len; i++) { children[i].visit(); } this.render(); // reset our dirty markers this.isFrameDirty = this.isColorDirty = this.isTransformDirty = false; } |
At this point Chester unveiled the curtain and told me that he had written this simple 2D engine/demo using WebGL, that even falls back to the canvas API when there’s no webgl, supporting asynchronous loading of assets, sprite sheets (Texture Packer format) and tile maps (TMX files). He called it “ChesterGL” because it was his library.
He passed me the source code, I added a MIT license to those and placed them in a github repo for everyone to hack them.
Cool! Now for the rest of the stuff, I’ll leave that for another post, like how Chester approached the canvas API fallback. Spoiler: it was easy, canvas provides a setTransform() method!
1 For more info on this, head over to the opengl docs http://www.opengl.org/sdk/docs/man/xhtml/gluPerspective.xml
You can have stupid ideas too
I have lots of ideas, and I like to discuss them with friends/colleges in order to test them before implementing them. This usually leads to ideas that are ok, ideas that are really good, ideas that suck and sometimes ideas that are plain stupid.
Assuming that you too can have stupid ideas is very important, because it can mean that you are thinking, and discussing your thoughts with someone else. This argument is good enough to make a stupid idea worthwhile.
I will also share some stupid ideas I’ve had with you:
When I was at the University, and we were learning Numerical Calculus, I came up with an awesome idea: poly-compress. You could compress a buch of data, just by defining the polynomial interpolation that would represent the data and then just “evaluate” the polynomial to reconstruct the original data. Sounds great! except that the data you need to create the polynomial is the same or more than the original information. Duh!
Today I was discussing a problem with a friend and I woke up with a great new idea, I rapidly emailed him with my proposed solution, only to find out after a few hours that it was the same thing that was already implemented, but with fewer comparisons: it was better, but marginally better. Duh!
I came to realize that the ideas were bad after discussing them with friends and trying to implement them. None of them was implemented of course, but just the exercise of thinking on how to implement them made me realize that they were pretty stupid ideas.
So… don’t be afraid to let everyone know that you can have stupid ideas too! You can even start a good discussion on why your idea is stupid and in that process you can come up with a good idea.
Conditional assignment on C
So, I’m used to ruby, and a good thing that I love is that conditionals also return values:
1 2 3 4 5 |
a = if test_condition "test is true" else "test is false" end |
Ok, perhaps that’s not the best example, but you get the idea. In fact, a better example might be this one:
1 |
a = test1 || test2 || test3 || test4 |
In this case, if test1 fails, test2 is executed, and so on. And it stops when the first test returns a valid true value (anything but false or nil). Nothing exciting here so far. What is cool about this, is that a will hold the value that short-circuited the conditional. In the previous example, if test1 and test2 returned nil, and test3 returned “blah”, then a would hold the value “blah”.
Let’s try the same in C (or any other variant, like Objective-C or C++):
1 2 |
void *obj = NULL; obj = test1() || test2() || test3() || test4(); |
First, if you have the proper warnings turned on (which you should, by the way) the compiler will warn you about assigning an (int) to a (void *), second if you disregard that warning, you will end up always with a 1 or a 0 (zero) assigned to obj, which is a BAD thing :D.
The Good Way™ to do this is through a temp variable:
1 2 3 4 5 |
void *obj = NULL; void *tmp = NULL; (tmp = test1()) || (tmp = test2()) || (tmp = test3()) || (tmp = test4()); obj = tmp; |
This way it will still only execute the conditions until one is met (tmp != NULL) and you will be able to rescue the value of that result.
Thanks to my friend JF for the heads up!
Better text areas in enki (or any other rails app for that matter)
When creating my site, I realized that I might be typing a lot of code snippets into this blog, and since usually pressing “tab” changes focus on input fields and not actually inserts a tab in the text I’m editing, I realized I had to “fix” that, here’s my solution:
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 |
# context: enki blog (http://www.enkiblog.com/)
# file: app/views/admin/posts/_form.html.erb
<% content_for(:head) do -%>
<%= javascript_include_tag 'admin/edit-preview' %>
<% end -%>
<%= form.inputs do -%>
<%= form.input :title -%>
<%= form.input :body,
:hint => "<a href='http://textile.thresholdstate.com/'>Textile enabled</a>. Use Ctrl+E to switch between preview and edit mode.".html_safe -%>
<%= form.input :tag_list, :as => 'string', :required => false, :hint => 'Comma separated: ruby, rails…'.html_safe -%>
<% end -%>
<%= form.inputs do -%>
<%= form.input :published_at_natural, :label => 'Published at', :as => 'string', :hint => 'Example: now, yesterday, 1 hour from now, '.html_safe + link_to("more…".html_safe, "http://chronic.rubyforge.org/") -%>
<%= form.input :slug, :hint => "Leave blank for an auto-generated slug based on the title." -%>
<%= form.input :minor_edit, :as => 'boolean', :hint => 'Minor edits will not show up as refreshed in feed readers. Use this to fix spelling mistakes and the like.' unless @post.new_record? -%>
<% end -%>
<script type="text/javascript">
$(document).ready(function () {
$("#post_body").css("font-family", "Menlo").css("font-size", "8pt");
var has_focus = false;
var lastKey = 0;
$("#post_body").bind('blur', function () {
if (lastKey == 9) {
// if selection is nothing, then insert a "tab"
if (this.selectionStart - this.selectionEnd == 0) {
var val = $(this).val();
var a = val.substring(0, this.selectionStart);
var b = val.substring(this.selectionStart, val.length);
$(this).val(a + "\t" + b);
// now set the selection
this.selectionStart += 1;
}
$(this).focus();
return false;
}
return true;
}, true);
$("#post_body").keydown(function (event) {
lastKey = event.keyCode;
});
});
</script>
|
It goes like this:
when post_body looses focus (the body text area for the post) and if last key pressed was actually a tab (you can loose focus by clicking somewhere else), then insert a tab where the selection pointer was, and move the selection pointer.
Oh, I also added some nice css styles for the textarea, like the lovely Menlo font and a specific font size.
It’s not the best solution, but it works.
Some wild ideas to implement:
- context-aware tab (like if you’re inside a ruby snippet, then insert two blanks instead of a “\t”
- be able to shift-up/down indentation levels
But… if you start doing all that, you end up with something more like a text editor than just a simple post creator in your blog app. So… this small change is what will work best for me now.
Lessons learned with Javascript
Some time ago I left my safe ruby & Objective-C lands to get into the bushy and wild javascript jungle. But surprise! it wasn’t that wild and there were some very mature and fun actors in here! Namely node.js and the V8 engine.
So, here are a few of the things I think I learned about javascript:
1 – Javascript is prototype1 based
Although some people may claim that javascript is an OOP2 language, I like to think that javascript is actually prototype based with lots of functional programming influence. Don’t get me wrong though, you can actually do some serious OOP with javascript (more on that later)
2 – Javascript can be fun!
Take for instance, jquery & jquery ui. Both of them are very well designed frameworks and actually very good programming practices.
3 – Namespaces
Although there are no actual namespaces, you can simulate them encapsulating functions/variables/objects inside other objects, for instance:
1 2 3 4 5 6 7 8 9 10 11 12 |
function foo() { console.log("global foo"); } // empty object var ns = {}; ns.foo = function () { console.log("foo inside ns"); } foo(); ns.foo(); |
This takes into consideration that the definition is made under the “global” namespace, which would be window’s closure. One way to make sure this is the wanted behaviour is to be explicit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
(function (window) { function foo() { ... } var ns = {}; ns.foo = function () { ... } // explicitly export symbols to the global namespace window['foo'] = foo; window['ns'] = ns; })(window); |
By creating the anonymous function (which receives as a single parameter the window object — you can pass other objects here if you want), you use your private closure inside: this way you do not contaminate the global namespace and only export the symbols you really want to export.
4 – Classes, Objects and being nice
In many places, you will see that the usual way to create a class is something like this:
1 2 3 4 5 6 7 8 9 10 |
// option 1
function MyClass() {
}
// option 2
var MyClass = function () {
}
// both options let you do this:
var obj = new MyClass();
|
What happens here is that the constructor is also the definition of the prototype for future objects, so things can get messy… In the end, looking at how frameworks like jquery & others do things, I opted for this way:
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 |
// empty definition var MyClass = function () {}; var MyClass__prototype = { attribute1: "something", attribute2: null, // these are instance functions/methods foo: function () { }, bar: function () { } } // these are class functions MyClass.class_function1 = function () { } MyClass.class_function2 = function () { } MyClass.prototype = MyClass__prototype; MyClass.create = function () { var o = new MyClass(); // initialize o here ... return o; } // usage: var someObject = MyClass.create(); |
This way, the constructor is clearly separated from the class definition, leaving no garbage in the object’s namespace.
5 – Add “static” typing through comments and check with closure compiler
Google’s closure compiler is a very handy tool that lets you “compile” your javascript code, but it also checks the code for common mistakes and also, if you comment your code The Right Way® then it also type-checks your code:
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 |
/** * @constructor {SomeClass} */ var SomeClass = function() {}; var SomeClass__prototype = { /** * the position of the object * @type {Object.<string,number> */ position: { 'x': 0, 'y': 0}, /** * this object's children * @type {Array.<SomeClass>} */ children: [], /** * adds a child - z and tag are optional * * @param {SomeClass} child * @param {number=} z * @param {string=} tag * @return {SomeClass} */ addChild: function (child, z, tag) { } }; |
Anyway… you get the idea. The whole thing is very inspired in jdoc and you should check the reference.
In order to compile the code, you can download the application (a .jar) and run it from the command line, or use the online application.
This is highly recommended for every javascript project since it will let you catch silly errors.
6 – Object properties are COW3 (at least on V8)
NOTE1 this is just an assumption of mine. Didn’t have the time to check it.
NOTE2 this is just something funny and not really relevant, but I find it very interesting.
When debugging my application I created a few simple objects just to see how they look under the debugger and also to learn a little bit more. So take for instance this simple example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var A = function () {}; var A__prototype = { prop1: "lala", prop2: "lolo" } A.prototype = A__prototype; A.create = function () { // simplest constructor ever return new A(); } // now test the code var a = A.create(); console.log(a.prop1); console.log(a.prop2); a.prop1 = "something else"; console.log(a.prop1); console.log(a.prop2); |
If you place that simple example on an html page and load it in Chrome and check the debug console, you will see what you expect:

But if you set a breakpoint on the creation line, and trace through the code, something interesting appears:

As you can see, the object a is empty, but the prototype shows the properties as expected:

but… as soon as the property is written, it is “promoted” to the object’s closure:

Which I think is really cool :-)
UPDATE: This whole point is basically the result of javascript being prototype-based: an object holds reference to a common prototype, until it needs to be different, in this case, when the property changes specifically in the context of that particular object.
So what happens when you modify nested objects? take for instance the updated example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var A__prototype = { prop1: "lala", prop2: "lolo", prop3: { 'x': 0, 'y': 100 } } var b1 = A.create(); var b2 = A.create(); console.log(b1.prop3); console.log(b2.prop3); b1.prop3.x = 500; console.log(b1.prop3); console.log(b2.prop3); |
If you set a breakpoint right before the creation of b1, you will notice that when you modify b1.prop3.x, it is also modified in b2. This is obviously not the intended behaviour. One way to fix this is with accessors and setters:
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 |
var A__prototype = { prop1: "lala", prop2: "lolo", prop3: { 'x': 0, 'y': 100 }, setProp3: function (x, y) { this.prop3 = { 'x': x, 'y': y } } } var b1 = A.create(); var b2 = A.create(); console.log(b1.prop3); console.log(b2.prop3); b1.setProp3(500, 100); console.log(b1.prop3); console.log(b2.prop3); |
By doing it this way, prop3 is modified the way we wanted. This is actually very important and you might want to take that into account when creating complex objects and inserting them in the prototype.

Conclusions
I have to admit that coming from a language that is as beautiful and simple as ruby, I was a bit afraid of testing javascript, specially since most of what I remember of javascript is what I learned in the 90s. After giving another look at javascript and seeing that if you commit yourself to respect the good practices, javascript can be quite fun!
In the end, I hope that some of the lessons I learned from re-learning javascript might be useful to you.
1 http://en.wikipedia.org/wiki/Prototype-based_programming
First post (again)
So, new home – hope to keep it updated this time.
Btw… too lazy to update the theme for enki.