Thursday, 23 December 2010

Building FFMPEG on Mac OSX Snow Leopard

FFMPEG is an amazing set of video and audio conversion tools, accessible via the command-line. It's rather fiddly to use, but being a command-line program it can be easily integrated into your server-side tools. The sequence of steps below worked perfectly for me on Snow Leopard with XCode 3.2.4 installed.

cd ~
# checkout the latest version of the source
svn checkout svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg
cd ffmpeg

# enable mp3 support (you need to install lame first. omit --enable-libmp3lame to build without it)
./configure --enable-libmp3lame --enable-shared --disable-mmx --arch=x86_64

# compile
make

# install
sudo make install



Example Commands


Here are some of the commands I've run so far..

Rotate a video 90 degrees clockwise (good for films shot in portrait


ffmpeg -vf "transpose=1" -i input.mp4 output.mp4

Note that there are many tutorials on the web that suggest you should use --vfilter "rotate=90" to rotate a video. This no longer works, as vfilters has been renamed vf, and the rotate option has been removed. As of Dec 2010, the above command does work.

Convert a mp3 to a flv audio file


ffmpeg -y -i myfile.mp3 -f flv -acodec libmp3lame -ab 64 -ac 1 myfile.flv

I'm using this command as part of a project I'm working on, flv is better than mp3 as you can stream (using flowplayer) an flv in such a way that user can jump around to any point of the audio without needing to download it all to that point. However, this is quite fiddly, a future blog post will explain how I did this!

Tuesday, 7 December 2010

find command - search ignoring svn folders

find . -not \( -name .svn -prune \) -name 'search-pattern'


Very handy.

Syncing web servers with rsync

rsync is an amazing useful file tree synchronisation command-line tool. It's included by default on mac OS X.
Essentially you point it at a remote source directory and a local directory and it'll make the local directory reflect the remote one exactly in an amazingly fast manner. It is able to do this by only sending the changes to files across, and even then it compresses those changes so downloads are super-quick.

This means it's an excellent tool for updating the contents of remote web servers.

Now in a standard linux way, rsync is incredibly flexible and Google searches give you tons of seriously complicated stuff on it, most of which can be ignored if you just want to sync folders. For instance most tutorials include how to set up the rsync deamon, and how to make that secure.
In fact you don't need to do this at all (though I'm sure it's really useful in some circumstances), you can simply run rsync directly. It'll log in using ssh, so make sure you have a ssh user set up.

The best way to use rsync is to perform a PULL from your remote server..

eg

  • ssh to your remote server

  • run rsync pointing it at the machine holding the data to sync



Example Command



Log into the remote machine (e.g. the web server) and type:

rsync -avz --exclude '.svn/*' -v --delete user@example.com:path-on-example-server/ /path-on-this-server/


This command connects to example.com as the user 'user' and will sync the folder path-on-this-server with the path-on-example server on example.com. --delete means delete any files on this server that are not on the one we're syncing with. --exclude '.svn/*' will ensure that any svn folders are not copied. This is really handy.

Tuesday, 30 November 2010

CSS: Make a 2-column scrollable list

Trying to make a 2-column list which scrolls on demand, and doesn't break the layout when the scrollbars appear is rather fiddly in CSS.

This solution uses a UL, where the LI elements are set to float left, and the width of each is set to 50%. Note that I've used the CSS3 property box-sizing (or -webkit-box-sizing) to make the 50% widths include the border and padding. Without this the total width of two 50% elements with a border adds up to more than 100% and the layout breaks.

Note that the height of each element must be set explicity.

Monday, 29 November 2010

Simple method of horizontally centering a DIV of unknown width

Centering in CSS is always a pain. If you are just centering text, or you are using (god forbid) IE6 then you can simply use the text-align property. If you are centering something of a known width, it's easy too, just set margin-left and margin-right to 'auto' and all is good. However, if you don't know how wide the element is going to be, for example, you have an element that expands to fit some text pulled from a database, it's a bit tricker.

There are loads of hacks around of varying reliability and complexity, but the simplest method I have found yet is the following.

  • The outer div is set to text-align: center

  • The inner div is set to display: inline-block



That's it. The fact that the inner div is set to inline-block means it picks up its parent's setting of text-align to center itself. Is kinda wierd, but works on all the browsers I've so far tested.

Thursday, 25 November 2010

Setting permissions on Amazon AWS S3 buckets using S3cmd

Calvium stores virtually all of its toolkit data on S3 servers. We often find ourselves using Cyberduck to manually upload and download files when required. One thing that is a pain though is setting permissions. Cyberduck doesn't appear to allow you to set the permissions on all files within a folder recursively. When you have a lot of files this can be a real pain. Happily s3cmd comes to the rescue! s3cmd is a third-party (e.g. not created by amazon) command line client for S3 which runs on linux, unix, and also MacOSX. It may compile on Windows, I haven't tried.


1) Make everything in a bucket public (e.g. everyone has read access)


s3cmd setacl s3://myexamplebucket.calvium.com/ --acl-public --recursive


2) Make everything in a bucket private (e.g. accessible only to the creator)


s3cmd setacl s3://myexamplebucket.calvium.com/ --acl-private --recursive


The above commands also work on folders within buckets, or on individual files (the --recursive option is not required in this last case). As you can imagine there are many more options (type s3cmd --help to see more help).

3) Disable Directory Listing in a bucket


s3cmd setacl s3://myexamplebucket.calvium.com/ --acl-private


By default, new buckets will list all of the files within them. This isn't usually a good idea though, as it makes it very easy indeed for someone to scape all the content of your site. The command above just omits the --recursive option. For new buckets it's probably best to run command (1) before (3) so that your files are actually readable.

Wednesday, 24 November 2010

Mac OSX - Making the finder search work (almost) properly

One thing that has irritated me for a long while is that the search box in the top right of the finder window in mac osx defaults to searching my whole mac, and not the folder I'm currently looking at. If I wanted to search the whole Mac I'd use the Spotlight search wouldn't I Mr Jobs?

Anyway, I just discovered that it's possible to change this behaviour. Open Finder, go to the menu and choose Finder / Preferences / Advanced, and select 'When performing a search: Search the current folder".



So much better!
Now I just need to find a way to make it search by FIle name and not file contents.

EDIT: Apparently there is no way of defaulting to search by file name in Snow Leopard. However, in finder you press CMD-SHIFT-F, then it will put the cursor in the search panel, and set it to search by file name. Not too bad at all!

Disabling file cacheing on the server using htaccess

Recently I've been testing our web app tools locally using MAMP. These apps eventually end up making changes to files in the file system. I've been finding however that the changes are regularly not picked up in the browser until I empty the browser cache. This is kind of irritating as you can imagine.

The solution was to define a .htaccess file in the directory containing the editable content files that prevents browser cacheing. Obviously make sure this is only used locally during testing! This also requires the Apache module mod_headers - MAMP 1.9.4 (and probably other versions too) include this by default.

# when in local mode, never caches anything in this folder. 
<IfModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</IfModule>



Adapted from here:
http://www.askapache.com/htaccess/using-http-headers-with-htaccess.html

Wednesday, 17 November 2010

Zebra Striping Tables with Pure CSS

I've seen quite a lot of tutorials for this effect that use Javascript, particularly jquery.
You can do it with pure CSS though using the handy :nth-child(odd) and :nth-child(even) selectors in CSS3.
This is a fragment from a javascript errors dialog I created for an online code editor for Calvium.com

Amazon AWS S3 Buckets: Safely Granting 3rd Party Sites Access

Some services, for example unfuddle.com have a neat feature where they can automatically back everything up to an S3 bucket in case of issues. This morning unfuddle went down for a while, so when it came back up I thought it would be a good idea to finally set this up.



Unfuddle asks for the 'access key id' and 'secret access key' in order that their scripts can write direct to your bucket. This is great, but armed with both those keys an attacker can easily access ALL of the buckets associated with that account. Our main account has potentially sensitive data in some of the buckets, so there is obviously no way we'd share the keys to that account with anyone.

Instead, what we can do is to create a completely new AWS account, and from the main account grant access to the new account ONLY to the bucket that'll contain the unfuddle backups. Note that you do not need a credit card number to do this, as the new account will not 'own' any of its own buckets. Also note that usage charges for the backup bucket will be applied to the main account.

Here's how: (note this tutorial requires Cyberduck, a free S3 and FTP client).
  • Make a new email address such as aws-myproject@example.com.
  • Go to amazonaws.com, and sign up for a new account using the new email addres
  • When you are logged in, choose 'account' from the main menu, then 'security credentials'
  • In the passwords file, record the email you used, and the 'access key ID' and 'secret access key'.
  • Log in to your main AWS account using Cyberduck.
  • Create a new bucket, called, for instance myproject.example.com
  • Right-click the new bucket, click Info and click the Permissions tab
  • Click the cog icon, then Amazon Customer Email address.
  • Type aws-myproject@example.com. In the right column, choose WRITE
  • Repeat the last two steps, but choose READ in the right column. (this step is optional)
  • Your user now has read and write access to the myproject.example.com bucket.
Now you can go to Unfuddle project settings, and enter the backup bucket name, 'access key ID' and 'secret access key' associated with the aws-myproject@example.com account. Even if those details are ever compromised, an attacker will only be able to access the single bucket you set up.

Note that if you try to use Cyberduck to view the S3 account for the aws-myproject@example.com it will fail. This is because Cyberduck uses s3 features that assume that the account is signed up for S3 services (which requires a credit card). For the same reason using s3cmd (command-line tools for S3 acccess) to list all buckets will also fail. However, using s3cmd to view the contents of the specific bucket we have granted access to will succeed (for example s3cmd ls s3://myproject.example.com will work)

This tutorial assumes unfuddle, but will work for any third-party cloud service that wants to read or write to S3 buckets.

Thanks to Tom & Richard of Calvium for the idea, and for their help setting this up.


EDIT: 16-02-2011. This currently doesn't work properly on unfuddle due to their system failing in the same way that cyberduck does. Am in contact with them to sort it out

Monday, 8 November 2010

jQuery: Working with radio buttons

Each time I need to use radio buttons in jQuery I need to look it up - here's the best way to use them I've found so far..


<form id="my-form">
<input type="radio" name="group-name" value="value1">
<input type="radio" name="group-name" value="value2">
</form>



// set up the initial value (theValueToSet)
var $log = $("#my-form input[name=group-name]"); // #my-form is optional, but speeds up the search
$log.filter("[value="+theValueToSet+"]").attr("checked","checked")

// do something when the value is changed..
$log.change(function() {
var selectedValue = $(this).val();
});

// getting the value out again later on
var value = $("#my-form input[name=group-name]").val();


Monday, 25 October 2010

Remove the MobileMe icon from the menu bar on Mac OSX

The fact that Apple's MobileMe icon installs itself on my menu bar despite the fact I have no intention of ever using it was starting to annoy me. There's no obvious way of removing the icon or uninstalling the app I could find anywhere.

However, thanks to this post, it turns out to be really easy to remove it.

Simple hold CMD, and drag and drop the mobile me icon off the menu bar. It disappears in a puff of smoke never to be seen again. Hurrah!

Wednesday, 6 October 2010

Allowing SymLinks in Mac OSX Web Sharing

The Web Sharing feature in Mac OSX allows you to share a folder in your home directory via Apache.
What I often want to do is to temporarily share a web site or suchlike that I'm currently working on, so I can access it via my iPhone for on-device testing. So what I wanted to do was to create a symlink from my ~/USERNAME/Sites folder to the actual folder where I'm working.

However, by default, any SymLinks within Sites not be followed due to the apache configuration. Happily this can be easily fixed.

Edit the file at:

/private/etc/apache2/users/USERNAME.conf


Which by default looks like this:

Directory "/Users/USERNAME/Sites/"
Options Indexes MultiViews
AllowOverride None
Order allow,deny
Allow from all
/Directory


To add the FollowSymLinks option. So the file should look like this:

Directory "/Users/USERNAME/Sites/"
Options Indexes MultiViews FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
/Directory


Then all you need to do is restart apache and you are done!

From the terminal type:

sudo apachectl graceful

Tuesday, 14 September 2010

iPhone SDK: Running a selector after a delay..

Quite often I've needed to run a selector after a certain time interval. Usually what I've done is the following:

[NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(doIt:) userInfo:nil repeats:YES];


A shorter and slightly easier method is a selector on NSObject (now that's a base class with a lot of methods if ever I've seen one!)

[self performSelector:@selector(doit) withObject:nil afterDelay:1.0];


If you set afterDelay to be 0.0, you have a quick and easy way of making a selector run once the current run loop has completed.

Thursday, 9 September 2010

iPhone SDK: What NSURL methods actually return

Apple's NSURL documentation has very little detail on what exactly the various NSURL methods actually return. It just says unhelpful things like 'returns the path' - what path?

Here's an example NSURL, and the output you actually get when using some of the methods.

NSURL* url = [NSURL URLWithString:@"http://username:password@www.example.com:888/folder1/folder2/filename.html?query1=value&query2=value#anchor1"];
[url scheme] -> "http"
[url user] -> "username"
[url password] -> "password"
[url host] -> "www.example.com"
[url port] -> "888"
[url path] -> "/folder1/folder2/filename.html"
[url lastPathComponent] -> "filename.html"
[url pathExtension] -> "html"
[url fragment] -> "anchor1"
[url absoluteString] -> "http://username:password@www.example.com:888/folder1/folder2/filename.html?query1=value&query2=value#anchor1"

Wednesday, 8 September 2010

Mac OSX Terminal: Recursive list of files in directory excluding .svn and .DS_Store folders / files

Those pesky .svn and .DS_Store files and folders are the enemy of many a terminal command..
Here's how to get a handy list of all files in a folder without them, in a simple format for later processing.

find * -type f | grep -v "\.svn" | grep -v "\.DS_Store"


Outputs:
App-Info.plist
Default.png
GpsDrawTheme/theme.json
RootModule/code/common.js
RootModule/code/db.js
RootModule/code/drawing.js
RootModule/code/drawingMenu.js
RootModule/code/index.js
RootModule/code/instructions.js
RootModule/code/myDrawings.js
.. etc


I'm sure there's a way this could be simpler, but this works for me.

Monday, 6 September 2010

HTML5 Local Storage

There are a number of different technologies for storing data locally in the web client. Cookies, SQLite (in those browsers that support it), the offline cache manifest, and also 'Local Storage'. If you simply want to store some name-value pairs, such as user config data, local storage is by far the simplest option. Up until today we had been using Brian le Roux's lawnchair for local storage, which we used in the mode where it wraps SQLite (specifically the Webkit version). The fact that all requests were asynchronous, while nice in most situations, didn't fit our model. So I've switched to localStorage instead, which has the added bonus of being ridiculously simple.

var text = localStorage.getItem("foo");
if (text === "hello") {
alert("You've been here before!");
} else {
localStorage.setItem("foo", "hello");
}


The system doesn't support storing javascript objects or array though. Happily, this is easily fixed with a combination of JSON.stringify and JSON.parse to move the object to and from a string representation.

var st = localStorage.getItem("foo");
var ob = JSON.parse(st);
if (ob && ob.text === "hello") {
alert("You've been here before!");
} else {
var toSave = { text:"hello", other:[1,2,3] };
localStorage.setItem("foo", JSON.stringify( toSave ) );
}


You can clear the contents by using the localStorage.clear() method.

There's a simple demo HTML5 local storage in action available here

Wednesday, 1 September 2010

MacOSX: Opening documents, folders, and applications from the command line

The Mac OSX command line has a very handy 'open' cp,,amd which tells the Mac OS UI to open the item you pass in. This is great for switching from using the terminal to using the UI for those times when the UI is more convenient.

Open the current folder in Finder
open .


Open a file using the default application
open mydoc.txt


Open a file a specific application
This is the same command as right-clicking on an item in finder and choosing 'Open With'. It can be really handy for testing an html file in a specific browser.

open -a /Applications/Safari.app index.html

Tuesday, 31 August 2010

Bourne Shell Script Commands

Here's a bunch of bourne shell script commands I use on a regular basis
Using variables
VARNAME=3
echo The value is $VARNAME


Concatenating a list of text files
This is most useful when the list of files is long.

files=(
a.txt
b.txt
c.txt)
for p in "${files[@]}"; do cat "$p"; done > output.txt


Check to see if file exists

if [ -f filename ];
then
echo "OK"
else
echo "ERROR: File not found"
exit
fi


Note that the spaces before the -f and after the filename are essential. Can be irritating if you forget!

Check to see if a directory exists

if [ -d directoryName ];
then
echo "Directory OK"
else
echo "ERROR: Can't find directory"
exit
fi


Checking a script is running on a particular machine
if [ "`hostname`" == "myhost.calvium.com" ];
then
echo "this is the right server";
fi;


Note that the spaces around the [, == and ] are ESSENTIAL. This gets me every time..

Wednesday, 25 August 2010

Pop up a list of options - iPhone SDK

Here's a quick snippet for popping up a list of options using the UIActionSheet in iPhone OS.

What's slightly confusing is that the index of the 'cancelButton' is 1, and 'destructiveButton' is 0, even though 'cancelButton' is listed first in the initWithTitle selector. This gets me each time!


// place this code in a UIViewController subclass

- (void)debugButtonPressed:(id)sender
{
UIActionSheet* action = [[UIActionSheet alloc]
initWithTitle:@"Menu"
delegate:self
cancelButtonTitle:@"Continue"
destructiveButtonTitle:@"Quit"
otherButtonTitles:@"Debug",nil ];
[action showInView:self.view];
[action release];
}

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
switch (buttonIndex) {
case 0: // Quit
NSLog(@"Quit");
break;
case 1: // Continue
NSLog(@"Continue");
break;
case 2: // Debug
NSLog(@"Debug");
break;
}
}

Converting between rgb and hex colors in javascript

Recently I've need to be able to convert between rgb and hex colors.

Here's the javascript functions I used.

function hex2Rgba(hexColor, opacity) {
// Only accepts #123456 format for now
if (color[0] === '#' && color.length === 7) {

var r,g,b;
r = parseInt(color.substring(1,3), 16);
g = parseInt(color.substring(3,5), 16);
b = parseInt(color.substring(5,7), 16);

//
return "rgba("+r+","+g+","+b+","+opacity+")";
}
return null;
}

Obviously this is pretty basic, and doesn't support the #123 format.

For converting in the other direction I found this code on stackoverflow..

function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

Tuesday, 24 August 2010

Profiling Javascript Performance in Safari 5

We're currently in the process of building some pretty large and complex javascript apps here at Calvium. One of the parts of the system was running rather slower than it should have, so I took it upon myself to find out why. It turned out that all of the tools I needed to track down the performance problems were available right in the browser I was using - Safari 5 (and also Chrome, which shares the same engine) has an excellent Javascript Profiler available in the Inspector.
Using it is as simple as opening the page you want to profile, and in Safari, going to Develop / Web Inspector.
Once there, click the Profiles button and select 'enable profiling for this session'.

You can control the profiler by clicking the black circular 'record' button at the bottom left. When you stop recording you'll get a breakdown of the percentage of the time spent in each function. This can be handy, but often what you really want is to profile a very specific part of your app, for instance the process kicked off when a particular button is pressed.

Luckily there are some console commands you can insert into your Javascript to start and stop the profiler automatically.

Here's an extremely simple example. Here the goal is to find out which function is causing the slow operation of this script - is it slowFunction, or fastFunction? Guesses on a postcard please..

<html>
<head>
<script type="text/javascript">
setTimeout(function() {
// start profiling
console.profile("why so slow?");
slowFunction();
fastFunction();
// stop profiling
console.profileEnd();
}, 2000);

function slowFunction() {
for(var i=0; i < 100; i++) { stuff();}
}

function stuff() {
var count = 0;
for (var i=0; i < 1000; i++) {
for (var j=0; j < 1000; j++) {
count = count + 5;
}
}
}

function fastFunction() { var j = 23; }
</script>
</head>
</html>


When you open this page in Safari and run the profiler you get the following output:



The entries in the 'self' column shows the percentage of the profile time the execution of that particular function took - excluding time taken executing other sub-function calls made in that function. Here we can see that 'slowFunction' only took 0.02% itself, but 'stuff' took 99.93%. Looks like 'slowFunction' itself doesn't need any optimisation.
The 'total' column shows the time including any sub-function calls made, and here we can see that 'slowFunction' takes a massive 99.95% of the program execution. We can discover why this is easily using the Profiler tool. (I know its obvious in this case, but imagine with a huge complex app!).

You can change the way the results are displayed from the default 'Heavy (bottom up)', which shows each function individually, to the 'Tree (Top Down)' view. The tree view shows the call stack, and the time taken for each function along the way. Using this we can quickly drill down to discover that 'slowFunction' calls 'stuff', and that's why it takes so long. You can also see how many times each function is run.

Using this technique, you can easily discover the parts of your app that need optimisation. I manage to speed up the screen loading of a part of our application by a factor of six by identifying one particularly slow function that was called a huge number of times.

There's more info on using the 'console' javascript API on the apple developer site

SVN Commands I Actually Use..

I thought that I should paste in a bunch of SVN commands I actually use on a regular basis, mostly so I don't lose them. Also, perhaps they'll be useful to someone one day..



See which files are changed in my working copy
svn status


See which files would be changed if I were perform an update (I call this 'query update).
svn status -u


Make SVN ignore a directory, such as an output or build directory
First cd to the directory contains the directory you want to ignore..
svn propset svn:ignore directoryToIgnore .


Show the last 5 log entries
svn log -l 5


Perform a commit of all changes in this folder, with a message
svn commit -m 'made app 20% betterer'


Add a file containing an @ symbol.

This is essential when adding hi-res iPhone 4 graphics to an XCode project, as these have the format myImage@2x.png, where the original file was called myImage.png. Essentially just add a @ to the end of the filename


svn add myImage@2x.png@

Using Lawnchair to save config data in a web app

Lawnchair, created by PhoneGap's Brian Leroux, is a simple wrapper to various local storage technologies such as the HTML5 local storage system or even cookies. You can store and retrieve Javascript objects or arrays with just a few lines of code.

We use Lawnchair quite extensively at Calvium. We currently have a few web apps for internal use designed to be run directly from the file system (I'll probably write some more blogs about this subject as it is quite an interesting problem). This is great as it means the web app can read local files using Ajax calls, but due to cross-domain restrictions it cannot send anything to a server. So we can't store anything such as user preferences on the server, so we need to store it locally.
This is where Lawnchair comes in..

The docs don't make a few things very clear, such as how you specify the 'adaptor' to use. This is how you tell the system where data should be stored - cookie, database etc. Here's where my example hopefully may help!



Here's an excerpt of the HTML file. You need to include Lawnchair.js (obviously), and LawnchairAdaptorHelpers.js, and the adaptor you wish to use (in this case WebkitSQLiteAdaptor).

<html>
<head>
   <!--lawnchair-->
    <script type="text/javascript" src="js/libs/Lawnchair.js"></script>
    <script type="text/javascript" src="js/libs/LawnchairAdaptorHelpers.js"></script>
    <script type="text/javascript" src="js/libs/WebkitSQLiteAdaptor.js"></script>
</head>
<body>
   <input type="text" id="myConfigInput"/>
</body>
</html>


(Note: here's a really handy little site for converting HTML example code into a format you can copy into blogger)

Here's the javascript..
 // create the lawnchair object, telling it to create a table called myapp, using the 'WebkitSQLListAdaptor'.
var _lawnchair = new Lawnchair({table: "myapp", adaptor: "webkit"});

// create the javascript object with my default data in it.
var _config = {"userSetting":"", "key": "config"};
// key is the string used to get the data out in the 'get' call below.

// Load the config
_lawnchair.get("config", function(r) {

// If there isn't an item in the database with the 'config' key set, you'll get null. Make sure we don't overwrite the default!
if (r !== null) {
_log("LoadFileDialog: config loaded.");

// TODO: might be better to merge..
_config = r;

// Update interface with the values we've loaded.
}
});

// Note that the get function is asynchronous, so the get may not have completed by this point.

Thursday, 19 August 2010

Conditional Compilation in HTML

I'm currently building a large and fairly complicated app using JQuery'd Javascript, HTML and CSS. To keep the javascript code manageable and maintainable, I've arranged everything into classes, with one class per javascript file, and the filename of the JS file matching the class name. CSS files quickly become unwieldy too, so I have a similar approach with these.
This makes remembering which file contains the code I want very easy, but of course it means my app has dozens of JS and CSS files. As all web developers know - lots of files means lots of requests to the server means a sloooow site.

So, obviously, the answer is to concatenate all your JS files into one long file, and then use a tool like Yahoo's Compressor to shrink the javascript file into a fraction of it's former size.

I make a shell script like this:

jsfiles=(
trees.js
toast.js
armchair.js
)

for p in "${jsfiles[@]}"; do cat "$p"; done > code.js

java -jar yuicompressor.jar -o release/code-min.js codejs


So this is all great, but it left me with an issue. While I'm developing and debugging, it's essential my page links to the dozens of original javascript files so I can trace errors back to the source files, and set breakpoints more easily. But I need a version of the HTML page which links only to the minified version of the javascript and css files.. For a while I did keep two versions of the HTML, but as the page got more complicated keeping two files up to date wasn't practical.

My solution was to implement a basic 'conditional complication' system - where I could mark parts of the HTML file as being debug-only, and other parts as release-only. I knocked together a build script that would take the original HTML, knock out the debug parts, and uncomment the release only sections.

<head>
    <!--DEBUG-->
    <script type="text/javascript" src="js/trees.js"></script>
    <script type="text/javascript" src="js/toast.js"></script>
    <script type="text/javascript" src="js/armchair.js"></script>
    <link rel="stylesheet" type="text/css" href="css/trees.css"/>
    <link rel="stylesheet" type="text/css" href="css/toast.css"/>
    <link rel="stylesheet" type="text/css" href="css/armchair.css"/>
    <!--ENDDEBUG-->

    <!--RELEASE
    <script type="text/javascript" src="code-min.js"></script>
    <link rel="stylesheet" type="text/css" href="style-min.css"/>
    ENDRELEASE-->
</head>
<body>
</body>


Here's an example. Note that the release section is commented out - this means I can open the page directly and be in 'debug mode' with full access to all the script and css files via my browser's inspector.

Then it's a case of running a simple regex script (I used 'jsc', the javascript script engine built into Safari) to make the release version.

var i = arguments[0]; // the first parameter - e.g. the content of the HTML file

// Replace debug block with nothing..
i = i.replace(/<!--DEBUG[\s\S]*?ENDDEBUG-->/g, ""); // /g ensures EVERY match is replaced, not just the first. *? means use the smallest match (default is largest)

// Remove comment around production
i = i.replace(/<!--RELEASE([\s\S]*?)ENDRELEASE-->/g, "$1");


Simple hey?

Syntax Highlighting in Blogger Posts

Code examples on web pages work so much better if you have syntax highlighting. Blogger.com doesn't have this feature enabled by default but it's easy to add.

Without..

function foo(a,b,c) {
return "Ugly!"
}


With..
function foo(a,b,c) {
return "Good hey?"
}


Here's the tutorial I used. Thanks Luka Marinko.

PhpStorm - the best web development IDE out there

Back in my HP days I used to use a great plugin for Visual Studio called Resharper. It made a huge difference to my productivity - adding great code navigation tools (I could open a file, and jump to the function I wanted with just a couple of keypresses), code generation (Pop! There's another property with getters and setters. Pop! there's a try-catch-finally statement to wrap the 'dangerous' code I just wrote).
Since then loads of other IDEs (eclipse, netbeans) have added similar features to this, but none I've tried have been as smooth to use as Resharper was. For this reason I was quite excited when the company behind Resharper, JetBrains, launched PhpStorm and WebStorm. WebStorm is for Javascript, CSS, and HTML developers while PhpStorm includes everything in WebStorm but adds (predictably) PHP development.

Of the many, many cool features, here are some of my favourites:
  • Super-clever code highlighting for Javascript. Every IDE does syntax highlighting, but WebStorm lets you know not only that something is a variable, but if it's global, local, a parameter, or even an implicitly-defined one (please avoid these, readers!). Very cool - and very handy for tracking down errors too.

  • Code Navigation. You want to go to the function called 'doStuff' in the file called 'things.js'. You could use the mouse, scroll through your list of files, click the file, then scroll through to find the function you want... Or, you can press CMD-SHIFT-N, and type the first couple of characters of the filename, hit enter, then press CMD-7, and type the first couple of characters of the function name. Hit enter and you're done! With a bit of practice you'll be flying through your code. I'm a bit of a keyboard shortcut junkie - so this app is great!
I won't bore you with all the other cool things it does, but suffice to say I tried the demo, and liked it so much I bought copies for everyone in the company.

At the time of writing Jetbrains are doing a 'startup discount plan' where you get a 50% discount for new companies - this saved us a LOT of money so it's worth poking them if you take the plunge.

Equivalent to foreach in javascript

I happily developed in C# for a number of years during my time at Hewlett-Packard Labs. One of my favourite basic language features was the foreach function, for quickly iterating through the items in any type of collection.

foreach (MyObject ob in myObjects) {
ob.doSomething();
}


I started developing seriously in javascript a few months back, and eventually discovered a similar function..

var list = ["a","b","c"];
for( var i in list) {
console.log( list[i] );
}
// outputs a b c


Now it's not quite so neat as the C# version, as you get the index of the element in the array, rather than the element itself. This means you need to use the index to get the element out of the array - the array[i] part here.

You can also iterate all the properties of an object too.
var ob = {a:1,b:2,c:3};
for( var name in ob) {
alert( ob[name] );
}
// outputs 1 2 3

Run it here

However, there's a nasty gotcha with this approach. If someone anywhere in your javascript app, or any of the libraries it uses, or any code eval'd at runtime adds any properties or functions to 'Object' or 'Array' then your for in loop will return that property too!
This is of course, insane, but it's just how Javascript works. There's a great example of this problem if you use jsfiddle, a fab site for testing ideas using the 'holy trinity' of HTML, CSS, and Javascript. The libraries it uses add a whole bunch of stuff to Array including their own 'foreach' function.

Click here to see

Happily, there's a simple solution - just use the 'hasOwnProperty' method on an object to check that a property is not one inherited from the base class.

var foo = [1,2,3];
for( var i in foo) {
if (foo.hasOwnProperty(i)) {
alert( foo[i] );
}
}​


Click here to see

This is just one of the odd things in Javascript that can mess you around quite badly if you don't know about it!

You need an answer to a development question, but you only have five minutes...

If you are a developer like me, you'll constantly be coming against new problems. Maybe there's a bug in an API you're using, or perhaps the documentation for a system just doesn't make it clear how to achieve a certain effect. If a google search doesn't suffice, then I tend to use an excellent site I stumbled across a while back.

http://stackoverflow.com

It's a collaboratively-edited programming question and answer site. You post a question (like 'How do I get the focussed element on a page using JQuery?', and people post answers. On the surface it appears just like yet another forum, but I reckon it's much better. The key thing the designers added is a points system - every user has a rating that is shown next to every question, comment, or answer. If you ask a question deemed sensible or useful to other developers - you get points. If you post an answer, and it's marked as the best answer to the question, you get more points.
This feature obviously appeals to the competitive / slightly obsessive compulsive among us - people literally race to answer your question as quickly as possible!
For example, my slightly thorny iPhone UITableView question was answered correctly in three minutes!

There's an equivalent to stackoverflow for server admins too http://serverfault.com. It doesn't seem quite so active as stackoverflow, but it's still a great resource.