Thursday, December 11, 2008

Flash for Programmers Part 2: The Display List

The Display List in ActionScript 3 is comparable to the DOM on a web page. Through the Display List you can add and remove your View components.

I am not going to go into too much detail here are there are already many excellent articles about it online (http://www.adobe.com/devnet/flash/quickstart/display_list_programming_as3/) (http://developer.yahoo.com/flash/articles/display-list.html).

Suffice to say you will be calling addChild() and removeChild() quite frequently.

I am going to give you a few practical tips though...

Often (if you are doing truly modular MVC, which I will cover later), you will be firing off notes that may tell you to add and/or remove various components from the display list. You may fire a note which will ask to remove a child which doesn't exist though and this will cause your app to throw a nasty error.

Just like in real life, I find it handy to name my children i.e.

var dialog:Dialog = new Dialog();
dialog.name = "dialog";
this.addChild(dialog);

Later on, you may have some code which removes it.

this.removeChild(dialog);

However, if you aren't sure it will be there there is a better method

if(this.getChildByName("dialog") != null) {
    this.removeChild(this.getChildByName("dialog"));
}

What you are doing is first checking to see this child exists and if so, you can remove it. This should prevent any potential run time errors.

Wednesday, December 10, 2008

Programmer's Guide to Flash: Part 1 - The Document Class

While Adobe came out with Flex specifically to create an IDE for programmers to create ActionScript/SWF applications, it is actually possible for programmers to use Flash CS3 (normally seen as a design tool) to create Rich Internet Apps.

Most Flash programmers tend to regard Flex programmers in the same way that Web Developers regard .NET programmers. Flex (and .NET) programmers tend to be generalists who don't really know that much about interface programming and are afraid to get into the guts of a system. Flex itself is a 300k beast which may speed up your development, but it will slow down your application.

However you are in luck. With Flash CS3 Development, the only really hard part is knowing where to start. Once you are over the initial hurdle, you will find yourself in code most of the time.

Step 1:

First of all, open Flash CS3 and create a new project (File -> New... -> Flash File (ActionScript 3.0).
If you open the Properties Window you will see a box labelled Document Class. This is where you will put the Main ActionScript file which will control the application.







For now what you should do is save your .fla file and create an AS file in the same directory (say Main.as). In the Document Class you enter class name "Main".

Step 2:

Put the following code in Main.as

package
{

import flash.displa
y.MovieClip;

public class Main extends MovieClip {

public function Main(){

trace("I am in the main app");

}

}
}

When you compile this (Control -> Test Movie) this will open up an Output window printing out the trace statement ("I am in the main app").

While this is fine for your own project file, what do you do when you want to import 3rd party libraries or else write large multi file applications?

Step 3:

Understanding packages is important for the next step. A package name is basically a signature which reflects the organization of a file within folders. Therefore a package called com.adobe.webapis.flickr represents a path com/adobe/webapis/flickr and any files to do with this project are put in this folder.

i.e.
package com.yourcompany.project
{

import flash.display.MovieClip;


public class Main extends MovieClip {

public function Main(){

trace("I am in the main app");

}

}
}

This means Main in this case should be placed in the subfolder com/yourcompany/project and referred to in the Document class as com.yourcompany.project.Main.

Step 4:

You may want to move this folder to another location however (or else use a shared package vs copying it into your project, especially for common files). To do this, click on the Publish: Settings... in the Properties window which will bring up the following dialog.
















Click on the Settings... button next to the ActionScript version. There you will see the Classpath box. Click on the + symbol and navigate to the folder above the top of your package (i.e. if your package is in C:\lib\src\com\yourcompany\project, set the Classpath to C:\lib\src). You can add multiple class paths as well.





















And there you have it. A means of adding ActionScript to the Flash file and a means of splitting up your project into multiple files. When you want to call in your own custom classes, you import them according to their class name (the same as when you imported flash.display.MovieClip) i.e.

import com.companyname.util.StringUtil

Just remember to add it to the class path!

Friday, October 24, 2008

Freezing Gems

What is a gem and why would you want to freeze it?

In Ruby, there are times when you want to access pieces of functionality that other people of written (3rd party libraries) and you normally have 2 options. You can install a plug in or install a gem. Normally the method you use is determined by which ever is made available by the author.

Gems are installed on the host machine and are pretty handy when you want to run things in the command line or else across lots of projects, but their downside is that if you use a gem in a Rails project there is no automatic publishing mechanism when you deploy your site. You will need to log onto the remote host machine and install the gem manually.

Plugins are specific to Rails and are similar to gems in that they are also 3rd party libraries. However they are associated with your Rails project as opposed to your machine so they will get posted to the server on a regular deploy.

Freezing a gem is the process of transforming a gem into a plug in. Essentially the gem is "unwrapped" and installed into your Rails plug ins directory.
  1. Make sure the gem you want to freeze is installed.
  2. Navigate to your Rails project's home directory and type the following
  3. script/plugin install http://svn.ardes.com/rails_plugins/gems
    (this is the plugin which will freeze the gem)
  4. rake gems:freeze GEM=gem_name
Note that not every gem can be frozen successfully. Some gems rely on executables which are platform specific and these cannot be accessed from the plugins directory.

Monday, October 20, 2008

XSS Terminate

There may eventually be a time when you need to allow people to write some HTML on your site. Maybe you have a bulletin board or something or else possibly you are writing some kind of email app or wiki.

The main problem with this is that you potentially open your site to Cross Site Scripting (XSS) attacks (more info at http://en.wikipedia.org/wiki/Cross-site_scripting). Basically in an XSS attack, someone puts in a little JavaScript in your site via a user input and when someone else looks at the page the first person steals the other's cookies. In fact you can unwittingly open your site to XSS attacks just by forgetting to encode all your user inputted text by using the h() function.

This is essentially a backwards approach to the problem however. What you really want to do is close everything down by default and then make a mental effort to allow it to use HTML. Even then, you may run into the problem of people running script tags.

Enter XSS Terminate. This is a handy little plug in which will basically strip all HTML tags out of any field going to and from the database by default. You can additionally apply either Rails' sanitize method to strip out scripts while allowing some basic HTML tags or else use html5lib_sanitize to strip out the scripts while allowing for normal browser quirks (sanitize requires strict XHTML standards).

In any case, the real reason I am writing this is that the XSS terminate usage instructions contain a couple of errors.

Where the site says

  class Review < ActiveRecord::Base
xss_sanitize :sanitize => [ :body, :author_name]
end
I found this didn't work for me. After some trial and error I found the following fix

  class Review < ActiveRecord::Base
xss_terminate :sanitize => [ :body, :author_name]
end
I also had problems with
class Message < ActiveRecord::Base
xss_terminate :except => [ :body ], :sanitize => [ :title ]
end
instead I did the following

class Message < ActiveRecord::Base
xss_terminate :except => [ :body, :title ]
xss_terminate :sanitize => [ :title ]
end
Basically though you probably don't want to use :except without using :sanitize or :html5lib_sanitize. Ever... And I mean it... Otherwise the next email you get will be from your sysadmin (if you are lucky) or your lawyer (if you are not).

In any case, the next problem is that the HTML elements entered by the user will probably read your default stylesheets. While you may want this, you may actually want the HTML to look kind of clean and distinct from your site (to highlight the fact that it is user generated content).

There is no easy way unfortunately to reset the css in a specific section so I had to search around for a default browser stylesheet online and then manually prefix every element with .text-entry. Because I am a nice guy, I am including it here (just do a text replace on .text-entry to use your own class name).

Enjoy!

.text-entry div,.text-entry dl,.text-entry dt,.text-entry dd,.text-entry ul,.text-entry ol,.text-entry li,.text-entry h1,.text-entry h2,.text-entry h3,.text-entry h4,.text-entry h5,.text-entry h6,.text-entry pre,.text-entry form,.text-entry fieldset,.text-entry input,.text-entry textarea,.text-entry p,.text-entry blockquote,.text-entry th,.text-entry td {
margin:0 !important ;
padding:0 !important ;
background:none !important;
background-color:none !important ;
border:none !important ;
font-family: Arial, Helvetica, sans-serif !important ;
color:#000 !important;
text-transform:none !important;
}
.text-entry table {
border-collapse:collapse;
border-spacing:0;
}
.text-entry fieldset,.text-entry img {
border:0;
}
.text-entry address,.text-entry caption,.text-entry cite,.text-entry code,.text-entry dfn,.text-entry em,.text-entry strong,.text-entry th,.text-entry var {
font-style:normal;
font-weight:normal;
}
.text-entry caption,.text-entry th {
text-align:left;
}
.text-entry h1,.text-entry h2,.text-entry h3,.text-entry h4,.text-entry h5,.text-entry h6 {
font-size:100%;
font-weight:normal;
}
.text-entry q:before,.text-entry q:after {
content:'';
}
.text-entry abbr,.text-entry acronym { border:0;
}

.text-entry address,
.text-entry blockquote,
.text-entry dd, .text-entry div,
.text-entry dl, .text-entry dt, .text-entry fieldset, .text-entry form,
.text-entry h1, .text-entry h2, .text-entry h3, .text-entry h4,
.text-entry h5, .text-entry h6,
.text-entry ol, .text-entry p, .text-entry ul, .text-entry center,
.text-entry dir, .text-entry hr, .text-entry menu, .text-entry pre { display: block }
.text-entry li { display: list-item; margin-left: 10px !important }
.text-entry head { display: none }
.text-entry table { display: table }
.text-entry tr { display: table-row }
.text-entry thead { display: table-header-group }
.text-entry tbody { display: table-row-group }
.text-entry tfoot { display: table-footer-group }
.text-entry col { display: table-column }
.text-entry colgroup { display: table-column-group }
.text-entry td, .text-entry th { display: table-cell }
.text-entry caption { display: table-caption }
.text-entry th { font-weight: bolder; text-align: center }
.text-entry caption { text-align: center }
.text-entry body { margin: 8px }
.text-entry h1 { font-size: 2em; margin: .67em 0 }
.text-entry h2 { font-size: 1.5em; margin: .75em 0 }
.text-entry h3 { font-size: 1.17em; margin: .83em 0 }
.text-entry h4, .text-entry p,
.text-entry blockquote, .text-entry ul,
.text-entry fieldset, .text-entry form,
.text-entry ol, .text-entry dl, .text-entry dir,
.text-entry menu { margin: 1.12em 0 }
.text-entry h5 { font-size: .83em; margin: 1.5em 0 }
.text-entry h6 { font-size: .75em; margin: 1.67em 0 }
.text-entry h1, .text-entry h2, .text-entry h3, .text-entry h4,
.text-entry h5, .text-entry h6, .text-entry b,
.text-entry strong { font-weight: bolder }
.text-entry blockquote { margin-left: 40px; margin-right: 40px }
.text-entry i, .text-entry cite, .text-entry em,
.text-entry var, .text-entry address { font-style: italic }
.text-entry pre, .text-entry tt, .text-entry code,
.text-entry kbd, .text-entry samp { font-family: monospace }
.text-entry pre { white-space: pre }
.text-entry button, .text-entry textarea,
.text-entry input, .text-entry select { display: inline-block }
.text-entry big { font-size: 1.17em }
.text-entry small, .text-entry sub, .text-entry sup { font-size: .83em }
.text-entry sub { vertical-align: sub }
.text-entry sup { vertical-align: super }
.text-entry table { border-spacing: 2px; }
.text-entry thead, .text-entry tbody,
.text-entry tfoot { vertical-align: middle }
.text-entry td, .text-entry th { vertical-align: inherit }
.text-entry s, .text-entry strike, .text-entry del { text-decoration: line-through }
.text-entry hr { border: 1px inset }
.text-entry ol, .text-entry ul, .text-entry dir,
.text-entry menu, .text-entry dd { margin-left: 40px }
.text-entry ol { list-style-type: decimal }
.text-entry ol ul, .text-entry ul ol,
.text-entry ul ul, .text-entry ol ol { margin-top: 0; margin-bottom: 0 }
.text-entry u, .text-entry ins { text-decoration: underline }
.text-entry br:before { content: "\A" }
.text-entry :before, .text-entry :after { white-space: pre-line }
.text-entry center { text-align: center }
.text-entry :link, .text-entry :visited { text-decoration: underline }
.text-entry :focus { outline: thin dotted invert }
.text-entry a {color:blue !important;}
.text-entry a:visited {color:purple !important;}

Thursday, October 09, 2008

Suppressing and Logging JavaScript Error messages

When it comes time to run your fancy AJAX site on production, you may find that there will occasionally be minor JavaScript errors (possibly from 3rd party sites, never your own of course) which will not only prevent your scripts from running but may also pop up some warning boxes on the end users' systems (especially if your target audience is made up of web developers who have "Disable JavaScript Debugging" unchecked).

Even if the user does not have debugging turned on, they may still see the error symbol in the status bar (and this does not exactly put their fears at ease, especially if they are trying to make a cash transaction).

Fortunately, you can suppress these error messages by using the following JavaScript code

function noError(){return true;}
window.onerror = noError;

Essentially what this does is catch any JavaScript errors and passes them to a null function. You should probably wrap this in a conditional which will only run on production and staging because as you are developing you will want to see these errors to prevent them from happening in the first place (i.e.
<%if ENV['RAILS_ENV'] == 'production' || ENV['RAILS_ENV'] == 'staging' %>
<script type="text/javascript">
function noError(){return true;}
window.onerror = noError;

</script/>
<% end %>
).

window.onerror, as it happens, can also pass in some useful variables if you want to log them somehow. These are the error message, the url and the linenumber.


function alertError(message, url, linenumber){
alert(message + " " + url + " " + linenumber)
return true;
}
window.onerror = alertError;


However, what you probably really want to do is log it to your server via AJAX as opposed to alerting the error message to the user (using jQuery below).

function logError(message, url, linenumber){
$.ajax({
type: 'GET',
url: '/javascript_error',
data: {message:message, url:url, linenumber:linenumber},
dataType: 'json'
});
return true;
}
window.onerror = logError;


On the server side, create a small function which will take in these parameters and log them along with the user's remote address and user agent ( request.remote_addr and request.user_agent in Rails).

There are some browser differences (and inconsistencies) with this however. For a start, while Firefox will give you the url of the JavaScript file in which the error occurs, Internet Explorer will only give you the url of the page that is rendered in the browser (i.e. what is in the location box). Safari does not seem to support these at all (Safari will suppress the error, but not run the alertError function) and IE in debug mode behaves the same as Safari.

Thursday, August 21, 2008

More CSS tips

Continued from yesterday...

Firefox 3 and Safari both support rounded corners in CSS (now if only IE would catch up).

You can use the following tags.

-moz-border-radius: 3px; /** for Firefox **/
-webkit-border-radius: 3px; /** for Safari/webkit **/

If you use these tags on a div it will be rounded in FF or Safari and display square in IE.

If you only want to round some of the corners (as opposed to all of them) here is the additional syntax in an example (where I rounded the top corners only).

-moz-border-radius-topleft: 3px;
-moz-border-radius-topright: 3px;
-webkit-border-top-left-radius: 3px;
-webkit-border-top-right-radius: 3px;

Wednesday, August 20, 2008

CSS tips

Been back in CSS today. Here are some things I learnt today.

1) text-transform will allow you to transform the text to uppercase, lowercase or capitalize i.e.

h1 {
text-transform: uppercase;
}

This is a handy alternative to typing everything out in upper case (which is bad because the designer may change his mind to switch away from all caps at some stage).

2) If you are going to use jQuery to show/hide a table, wrap it in a div and toggle that instead. This is because show/hide/toggle in jQuery changes something from display:none to display:block. A table's display is inline-table by default and setting it to block will lead to some unexpected results.

3) If you have to write CSS (or anything) for IE only, you can use conditional comments
<!--[if IE]>
Special instructions for IE here
<![endif]-->
It's best not to use special CSS code for IE at all, but in some cases it's unavoidable.

4) You can modify the sliding doors technique by using a single image (instead of 2 images). The advantage to using a single image is fewer graphics to download (as they are cached).

Thursday, August 07, 2008

Real MVC for the web

I recently read an article which talks about writing MVC for the web using jQuery (http://welcome.totheinter.net/2008/08/05/mvc-pattern-for-the-web/).

In any case, the author proposes building a full MVC controller in JavaScript (the example article is still in progress), which is interesting, but I think in some ways it is a little misguided, for I believe that the front end of the web is already MVC.

Model = HTML (provided it is written semantically and not structurally)
View = CSS (updating the style)
Controller = JavaScript

As long as you follow the principles of Unobtrusive JavaScript and keep your (X)HTML clean then you have MVC built in. XHTML is a form of XML after all (and XML is used to represent data/model).

Just a thought...

Thursday, July 31, 2008

Unit/Functional Testing RubyAMF

One of my current projects is using RubyAMF to communicate with Flash (http://rubyforge.org/projects/rubyamf/). On the whole this is really nice because it allows you to transfer Ruby objects directly to ActionScript ones (as opposed to translating the object into XML, sending the XML and then recreating the object in ActionScript).

However, Rails does not provide a built in transport mechanism for AMF, so we cannot run functional testing directly on the data call (as we could for an XML or HTML transport layer). This is a show stopper for a lot of people (Rails w/o Unit testing = a big mess of trouble when something goes wrong).

We can though serve both the HTML and the AMF formats depending on the request format. This means that we can test the object instantiation logic and make sure there are no errors in the controllers (though we cannot check the actual format of the data being served).

In the controller, instead of rendering AMF alone, do the following

respond_to do |format|
format.html {render :text => ""}
format.amf { render :amf => @photo }
end

Note: You will have to give the variable object instance scope using the @ sign so we can test for it

Then in the unit test file, you can test in the following manner

def test_get_photo
get :get_photo
assert_not_nil assigns(:photo)
assert_response :success
end

So you can at least test that the object got instantiated and no errors were generated.

Thursday, July 10, 2008

Writing Web Components in Rails

One of the problems most people run into when writing web components is the fact that you have to tie together 2-3 disparate elements (HTML partial, JavaScript file and/or CSS) into one contextual component.

As JavaScript and CSS files are normally placed in the head and the HTML partial occurs somewhere in the body, it can be hard to track down any missing pieces should they arise.

In RJS (built in Ruby JavaScript components) the normal procedure is to place the script tag next to the element in the HTML itself. This not only goes against Unobtrusive JavaScript principles, it is also butt ugly if you ever have to view the source code.

Thankfully, there is a more elegant solution.

Instead of rendering your JavaScript directly in the page, i.e.

<%= javascript_include_tag "my_component" %>

you wrap it in a content_for(:head) (this assumes you have placed a <%= yield :head %> in your application.html.erb template).

i.e.
<% content_for(:head) do %>
<%= javascript_include_tag "my_component" %>
<% end %>

This will place your JS file in the head where it belongs.

For those of you who use jQuery, here is an extra bonus tip.

Sometimes you may want to call in an HTML partial via AJAX (I will write a full tutorial on that later). If you do so using jQuery any script tags that are in the HTML partial will get parsed, loaded and eval(uate)ed automagically. The only caveat is that in this situation you cannot use the content_for(:head) wrapper (and if you call multiple files in this manner the order will matter as the scripts will be launched immediately as opposed to on document.ready).

Using these techniques, you can write discrete web components that encompass both markup and functionality.

Tuesday, July 01, 2008

Unobtrusive JavaScript and href="#"

Back in the old days of inline JavaScript, people would often attach JavaScript functionality to links either by using:

<a href="#" onclick="doSomeJavaScript()">Click Here</a>

or by using

<a href="javascript:doSomeJavaScript()">Click Here</a>

Anyways, there are problems with both. In the first instance, the user will get booted up to the top of the page in some browsers (that's what href="#" basically does). The second instance is better, but it is inline and that is something we want to avoid.

In the Unobtrusive JavaScript world we would basically have to use the first instance because the "a" tag will not display as underlined in some browsers without an "href" attribute.

Or would we?

I am not really sure where the metaphor for using links as actions came from, but as long as it is there and people are used to it we will often get designs from UI designers using them as such. Links are really supposed to take you somewhere, buttons are calls to action.

In any case, a much better way to implement this (if you cannot get your UI designer sacked) would be to do the following.

1) Set up a CSS class called something like "fake-link"
2) Style it like an "a" tag (underlined, blue, etc...)
3) In the CSS set "cursor:pointer" (this will ensure it changes into a little hand and looks like a link)
The class should look like the following

.fake-link {
cursor: pointer;
text-decoration: underline;
color:blue;
}

4) Assign this class to a div or a span

<div class="fake-link" id="clickObject">Click here to call a JavaScript function</div>
5) Do your unobtrusive thaing (in jQuery below)

$('#clickObject').click(function(){
doSomeJavaScript();
});

Voila! You have something that looks like a link which keeps the UI guy happy, but it is really a div with a click handler which keeps you happy.

Also, if you end up getting a new UI designer who realizes that links should take you somewhere instead of calling actions, you can restyle your fake-link to look like a button-ish kind of object with minimal effort.

Monday, June 30, 2008

Unobtrusive JavaScript and the "lang" attribute

One issue that has come up in using Unobtrusive JavaScript is how do you assign instance specific data to the element.

For example, in the old days (pre UJ) you could iterate over a bunch of objects (each with it's own ID) and hard code the ID into the on{Event} attribute

i.e.
<% for item in items %>
<div onclick="someFunction(<%= item.id %>)">Click here to select item</div>
<% end %>

But in UJ, on{Event} attributes are no longer considered good practice. If only there was a way we could somehow encode the id with the HTML like we could in Flex (Flex supports dynamic attributes on objects).

You can assign a dynamic attribute using JavaScript, but putting a script tag into the loop seems very inelegant and against UJ principles. The other way would be to render all the objects in JavaScript first and then re-render them in HTML. This does seem rather wasteful in terms of processing however and full of index dependencies when you want to merge the JS objects with their HTML siblings (extra loops, etc...).

My latest solution (which may not be 100% semantic XHTML compliant) is to use the oft ignored and hardly used "lang" attribute to store the ID data.

<% for item in items %>
<div lang="<%= item.id %>">Click here to select item</div>
<% end %>

I then pick it up in jQuery using

$('div').click(function(){
clickHandler(this);
});

function clickHandler(element) {
var id = $(element).attr("lang");
// do AJAX call with the id
}

The lang attribute is supposed to let the browser know what language to use to display the content, but when you think about it, isn't the content written in the language itself? Not only that, but this is mostly only really used for the HTML element and only in very specific cases would you need it on a div (case in point bilingual pages).

Whilst I will admit this is not a failsafe solution, it does seem to meet my needs. I am wondering if anyone else has come across this problem and what their solutions would be.

UPDATE
I just thought of a couple of alternative methods, but none that I like as much as the one mentioned in the article.

1) Loop through the elements in JS only and create the HTML elements dynamically using DOM creation.

Disadvantage: DOM creation is expensive. It also creates elements which are impossible to debug the HTML when viewing the source directly (though you can in Firebug).

2) Use a compound id tag and parse out the irrelevant data (i.e. id="article<%= item.id %>").

Disadvantage: The id attribute must start with a non numeric character so parsing is a requirement. You cannot have an id like id="365". Parsing is expensive and error prone.

Monday, May 19, 2008

Checkbox arrays in Rails

Rails has got some nice default form options available in the FormHelper, however the check_box still leaves a little to be desired. It's great if you have one or two disparate elements, but what about when you want people to choose from a list of items like the following?

Choose your favorite fruits.





Code
<form>
Choose your favorite fruits.
<div><input value="apple" id="apple" name="fruit" type="checkbox"><label for="apple">Apple</label></div>
<div><input value="orange" id="orange" name="fruit" type="checkbox"><label for="orange">Orange</label></div>
<div><input value="banana" id="banana" name="fruit" type="checkbox"><label for="banana">Banana</label></div>
</form>


In the example above, they all have the name fruit which means that if you choose all of them and submit them to the server, you will get the parameter string

"fruit=apple&fruit=orange&fruit=banana"

All well and good, except when you are in the controller and you try and get the value of fruit (params[:fruit]), you will not get an array with the values of ["apple", "orange", "banana"]. You will only get "banana".

I like bananas as much as the next guy, but I want all the fruit...

So how do you do this?

It appears you have to explicitly tell Rails that it is an array. You can do this by using the square brackets "[]"

Code
<form>
Choose your favorite fruits.
<div><input value="apple" id="apple" name="fruit[]" type="checkbox"><label for="apple">Apple</label></div>
<div><input value="orange" id="orange" name="fruit[]" type="checkbox"><label for="orange">Orange</label></div>
<div><input value="banana" id="banana" name="fruit[]" type="checkbox"><label for="banana">Banana</label></div>
</form>


Now when you call params[:fruit], you will get the array ["apple", "orange", "banana"].

Note that this will work with any other type of elements as well (as long as there is a [] directive to turn them into an array).

Monday, May 12, 2008

Turning autocomplete off

Most modern browsers have a handy little feature which will check to see if you have filled in a text box before, and if so it will present you with a history of what you selected.

For the most part this is a very useful piece of functionality but for one caveat. The browser does not fire any kind of JavaScript event when this happens. Dynamic form validation based on user input thus becomes a (to use Dave Chappelle's word) "biatch".

Fortunately after digging around a little I found that there is a handy little attribute called "autocomplete" which you can set to "off" on the form element.

<form method="post" action="/registration/create" autocomplete="off">

This will keep those nasty little history drop downs from messing up your input validation.

Thursday, May 08, 2008

A couple cool FaceBook games

I just got turned onto a couple of cool FaceBook games today.

Bumper Stars

http://apps.facebook.com/bumperstars/
Bumper Stars is a cross between pinball, pool and Pacman. Basically you have a little beaver whom you shoot off to eat fruit and you bounce off all sorts of things. Kind of stupid, but fun and addictive.


Who Has The Biggest Brain

http://apps.facebook.com/biggestbrain/?pf_ref=sb
Who Has The Biggest Brain is one of those rare games which makes you think and makes analytical thought into a competitive sport. There are about 7 or 8 varieties of brain tests and teasers from simple math to figuring out which random objects weigh more than the others, finishing puzzles and counting blocks. The first few times you play are the most fun as you are presented with brand new kinds of tests which make you learn new tasks (after that it gets more competitive but stretches your brain less). In any case I am a scholar!

Saturday, April 19, 2008

jQuery quirks

Ok folks. let's get technical here (been a while, hasn't it)?

So I decided to start using jQuery instead of Prototype as the JavaScript framework for my next project. Overall I am very happy with it (great plugins, good performance, cleaner overall structure, etc...).

It does have a few weird things about it though which people should bear in mind. Nothing that would stop people from using it, but things people should know.

In Prototype, the $() function returns an HTML element and the Prototype uses the prototype keyword to add extra functionality to the vanilla elements in the page (hence its name).

In jQuery, the $() function actually returns a jQuery object which is bound to the HTML element. This jQuery object then encompasses most of the functionality you will ever need on an element.

For the most part, this is a good thing. By using this strategy, jQuery is non invasive
and will play nice with any other JS framework (it even has a noConflict mode in case you want to use it with Prototype which will assign the $() function to any other combo you want).

However, when you use the $() function in jQuery, then you have to be aware that you are not really calling an HTML element so the standard HTML attributes may not be there.

Here is an example.

Let's say you have a text field


<input name="myTextField" id="myTextField" value="Hello Earth" type="text">

Without jQuery you would have to do this


var myTextField = document.getElementById('myTextField')


In jQuery you can simply use the $() function instead.

var myTextField = $('#myTextField');

However, let's say you need to update its value. You would think this would be the way to do it:

myTextField.value = "Hello Mars";

For some reason though, you find it is not working and this is driving you nuts. Why is this the case?

The reason is that myTextField is actually a jQuery object, not an HTML element. So the way to update a jQuery object's value is by using the val function.

myTextField.val("Hello Mars");

Once you remember that, then you should be plain sailing.

The only thing is that sometimes you may need to call an obscure HTML element attribute like scrollBy. There are plugins to deal with it, but nothing native in jQuery. Currently I am falling back to document.getElementById to get these. This is not necessarily a bad thing because jQuery, as I said before, is non invasive so it leaves the rest of your JS alone (as a good framework should).

UPDATE

I just found out you can use jQuery's get() function in order to access the actual HTML element(s) instead of using document.getElementById. In other words, the following should work:

myTextField.get()[0].value = "Hello Mars";

Note the [0] is needed because get returns an array of elements.

Wednesday, March 26, 2008

Review: jPod

jPod is the latest Douglas Coupland novel about programmers since Microserfs. It centers around a group of mildly autistic programmers in a video game company in Vancouver who all sit in the same area of the company because their last names begin with the letter "J" and in particular the lead character's life, Ethan Jarlewski.

While there are some interesting and thoughtful moments in the book, it unfortunately comes nowhere near the calibre of Microserfs due to the following reasons.

1) Wildly outrageous plot lines: I won't go into too much detail about these, but suffice to say where Microserfs was at least plausible (if slightly unrealistic), Coupland relies on ridiculous events to keep the story going in this case. Not only that, the characters are able to navigate these plot points virtually unscathed and unscarred (where as in real life these kind of things would require months of therapy).

2) Too many non-story devices: There is one part of the book where the number pi is printed to 100,000 places which uses up about 10 pages which is not story which no one will bother reading. These kinds of techniques are employed liberally throughout the book.

3) Too many pop culture references: It's as if Coupland has decided that the pop culture references are more important than the characters. In Microserfs they were cute, in jPod they are overwheming.

4) Inserting himself into the novel: Ok, Hitchcock liked to make cameos in his movies, but Coupland not only makes his characters reference him, he also turns up in his own novel and ends up being the deus ex machina (god in the machine). This makes you hyper aware you are reading a novel and you completely lose the ability to lose yourself in the storyline.

So, Mr. Coupland, if you ever get around to reading this and then writing another novel about the programming community please heed these issues. On the one hand I think there are enough interesting quirks about programmers to fill lots of books and so I am glad you continue to write about them (us), but please focus on the characters.

Sunday, March 09, 2008

Master of my domain

Hi All,
I just got myself a new domain (http://www.skuunk.com). The reason is that Blogspot.com is offering cheap domain via GoDaddy.com and I thought after having this nickname for nigh on 10 years it was time to buy the domain before someone else did (also I read somewhere that using blogspot.com in your domain is the equivalent of an aol.com or hotmail.com email address...shudder...).

Of course I forgot that I would have to re-register my blog everywhere (which is taking ages) not to mention set up all my stats stuff again. *sigh*. It's a blogger's life...

In any case, don't forget to bookmark the new address and to vote me up on Technorati!

Monday, March 03, 2008

IE8 will render in standards mode by default

http://blogs.msdn.com/ie/archive/2008/03/03/microsoft-s-interoperability-principles-and-ie8.aspx

Yay, the "geniuses" (genii?) at Microsoft are finally doing something right! IE8 will now render in standards mode by default (and if you want to make it run on IE7 mode you have to put in some meta tag thingy).

If by standards mode they mean it will render pages like Firefox then I am happy.

Now all they have to do is put some Windows update code out there which will permanently destroy all copies of IE6 so no one will even think of using it anymore.

In all reality and sadness, I know we should be encouraging everyone to use Firefox, but unfortunately most people just use their system's default browser...

I am not even really happy about Safari for that matter...

Sunday, March 02, 2008

How Digg and Reddit brought browsing back.

Are you old enough to remember when the Internet when it seemed to have a finite amount of information? Do remember the Darwin Awards? Can you remember the last time you actually saw an original joke online or in your inbox?

If so, then maybe you sometimes have a hankering for old days when rather than searching for things on the Net, you would just browse around just click on random things and occasionally come across sites like "The End of the Internet". These were the days when you had directories, not search engines, and you just had to take what you could get.

In any case, recently a couple of new(ish) sites like StumbleUpon, Digg and Reddit have brought the browsing back to the browser. These are sites on which other people post stories of interest and rather than searching for interesting content, the user simply browses through. Stories are ranked by other users and secret sauce algorithms are in place to try and keep out spammers and general exhibitionists so that the stories you see are guaranteed interesting.

When you click through these sites you end up in a fugue or a daze where the best of the Net is brought to you with minimal thought. One of the nicest features though is that while you can go down into subcategories, if you just go through the default flow you end up seeing truly new things that you never would have thought of. Sometimes getting exactly what you want can be the problem rather than the solution as it takes too much work to think about what it is you really want.

Hence the beauty of browsing. Browsing is actually a natural activity practiced by early homonids (during our Hunter/Gatherer phases) where rather than selecting exactly what we want to buy at the supermarket, we would forage and eat whatever came our way. Sometimes it was good, sometimes not so good, but it was always interesting. This is the reason brick and mortar shops still exist even though you can order everything you want online just by searching for it.

Browsing is also important in helping bring new options to the table that you wouldn't have otherwise thought of.

While blog sites such as BoingBoing also fulfill this function, they don't actually update fast enough. It's easier to click than to post and who has time to list every interesting link themselves. This is where the multi poster model works so well.

So if you need to waste time online like the old days (before you could be productive on the Net) then browse away.



IE8 Sneak preview

http://leakedtech.blogspot.com/2008/03/internet-explorer-8-beta-1-sneak-peak.html

So it looks like IE 8 Beta 1 is out. Even using VM with Parallels I am not prepared to try it out for myself.

It doesn't look like there are an JS changes but mainly CSS ones.

Now if they could just hurry up and kill IE6 then that would make my life much easier...

Tuesday, February 26, 2008

You know you are a web geek when...

  1. You watch more TV shows and movies on your computer than you do on TV and the movie theatre.
  2. You spend more time blogging about movies than watching them.
  3. You are genuinely excited whenever Apple releases a new computer (even though it only makes your current MacBook more obsolete).
  4. You IM people who are right next to you instead of talking to them.
  5. Your wife IM's you to get your attention.
  6. You don't need a blankie because your laptop keeps you warm at night.
  7. When you do finally get tired of using your laptop you pick up your phone and surf the web there.
  8. If it isn't online it doesn't exist.
  9. You open your laptop before you brew your first cup of coffee.
  10. When you call your laptop your wife and your wife your mistress.

Getting back to Flex

So one of my upcoming projects may involve Adobe Flex so I am trying to get my brain Flexy again. It's been almost a year since I coded anything in that language so I am trying to get back into all the usual concepts (code behind, cairngorm, etc...).

Of course the day I decide I am going to start looking at this, Flex Builder 3 is released (along with Adobe AIR, codenamed Apollo) which leaves me with a conundrum. Do I start this project in Flex 2 or 3? I am not really a fan of "brand new" tech as it normally has a lot of bugs that need working out, but those geniuses (geniui?) at Adobe have finally put in some backwards compatibility. Also it doesn't look like the language has changed much (mainly the IDE) which is a great relief (there was a huge jump between Flex 1 and 2).

So with the release of Adobe AIR I can finally call myself a Desktop developer too (as AIR allows you to write desktop apps with web app languages). If only they would switch over to Ruby from ActionScript though (then my life would be complete...).

Sunday, February 24, 2008

New Adobe camera has 19 lenses

 
This thing is cool. Not only does it allow you to make 3D pics, but you can also choose variable focal lengths in the picture (click on the link to see it in action).
 
I am guessing there is a software component to this too (duh).

Youtube is back up again!

Yay! Sign of relief...

Friday, February 22, 2008

Excel as a database

http://www.neopoleon.com/home/blogs/neo/archive/2003/09/29/5458.aspx

This is just too funny (especially the Kodak funtime camera).
Unfortunately they left out Powerpoint (which seems to be the preferred choice of my marketing team).

Thursday, February 21, 2008

Comment: Are you an Internet Producer or Consumer?

Most people who use the Net nowadays really fall into one of two categories.

1) Internet Consumers - This is most of us. We may occasionally paste some video into Facebook, but we normally use the Net to swap emails, read the news and occasionally look at pictures of other naked people.
2) Internet Producers - Leaving aside the techies for a moment (the people who "build" the Internet), these are the people who are obsessed with getting their points across, their opinions discussed, their crappy music demo listened to, and posting naked pictures of themselves online for the Consumers to look at (oh yeah, let's not forget those budding young stars trying to get their 3 minutes of YouTube fame).

Ok, so most of us probably fall somewhere in the middle. We blog, we may occasionally post something to YouTube, and maybe we daydream about being naked online before we realize what a bad career move that is...

For about 10 years now I have been making a living as one of these people who "build" the Internet. Were it not for this wonderful piece (pieces) of technology I would still be living in my parents' basement, but lo and behold, I now have a lucrative career. But you know what? There's not one of us "techies" who doesn't dream about either making history or having a blog so popular you only need to work on it 3 hours a day.

For a long time now, I have been pretty much a consumer outside of my professional life. I would post questions on bulletins when I had a technical question and lo and behold, someone would answer it. Tonight I decided to try and give back to the tech community, but every time I saw a question I knew the answer to, someone had beaten me to answering it.

So instead I decided to write this little article to keep you all amused.

It's my way of giving back to the community...

I must remember to post this on Reddit.com so I will get a few page views.

;)

Thursday, February 07, 2008

Evolution of Tech company logos

http://www.neatorama.com/2008/02/07/the-evolution-of-tech-companies-logos/

You gotta wonder what your new Nokia cell phone would look if it had the old logo on it...

Where is the computer?

http://www.macobserver.com/article/2008/02/06.8.shtml

Danish Police were apparently confused while trying to confiscate someone's 1G iMac thinking it was only a monitor.
  • 'Where's the computer?' he said.
  • 'On the desk. That's the computer,' I said.
  • 'No, the computer.'
  • 'That's the computer, dude.'
I wonder if "dude" is a literal translation from Danish.

Personally I remember the 1st generation iMacs and the guy was lucky not to get arrested for taste reasons alone (what with those garish candy coated colours...).

Wednesday, February 06, 2008

Why's Poignant Guide to Ruby

I wished I could re learn every programming language using a guide as poignant as this.

http://poignantguide.net/ruby/

I wonder if this guy has any plans to write a JavaScript tutorial too. I wonder how he would handle closures and prototype using elves and talking foxes...