Sponsored Link •
|
Summary
In my article on JavaScript, I observed that we need a new language that generates good and safe JavaScript, so that you no longer have to think about either JavaScript issues or cross-browser problems. Little did I know that the solution(s) had already appeared in the form of JQuery and CoffeeScript.
Advertisement
|
The fact that there have been so many JavaScript libraries attempting to solve the problem, and that the solution appears in not one but two pieces perhaps makes it understandable that it's not initially obvious. But once you see how well the solution works, you'll shake off the shackles of the old, and unleash your UI creative potential. This combination is compelling enough that Rails has included it as part of the standard distribution.
If you want to work across desktops, pads and handhelds, HTML5 looks like the only reasonable choice. And Windows 8 looks like it is going to be heavily based on HTML5, so these tools will also come in handy for that.
The browser problem is big. The amount of money that companies have invested to compensate for browser incompatibilities is huge. Entire jobs have been dedicated to that one issue.
Many have attempted to solve it by creating JavaScript libraries. Because of the size and pain of the problem, many libraries were created, and because this was primarily an open-source market and unencumbered by money, a solution has (relatively rapidly) evolved. I'm quite glad I only showed up after things have been sorted out.
The clear winner is jQuery. Go to the site and you'll not only see thorough documentation including lots of tutorials, but also the plugin framework that allows lots of other people to create easy-to-use add-ons. There are tons of plugins, including the very impressive jQuery UI.
A particularly nice way to browse through the library is Visual jQuery. There are a number of books out -- I have jQuery in Action and jQuery Cookbook but I hardly touched them before starting to write code -- the online resources are very good, and you can also find lots of examples in blogs.
jQuery is a facade over both JavaScript and the browser DOM. If you do everything via jQuery calls, you insulate yourself against cross-browser issues and also many of the gotchas of JavaScript -- however, you're still programming in JavaScript (a problem we solve in the next section).
Basically what jQuery allows you to do is discover parts and pieces of your UI and manipulate them. "Manipulate" means pretty much anything you can imagine, including modifying the CSS, creating and responding to events, Ajax, and all kinds of effects which, in combination with some of the mind-blowing plugins out there, rival what you can do with Flex. All this runs in the browser, without any browser plugins like Flash, Java or SilverLight.
You'll see more when we get to the example.
Although jQuery solves your browser issues, you're still working with a language (JavaScript) that wants to bite you at every turn (see the aforementioned previous article). Wouldn't it be nice to be able to program using a modern language that feels like Python, Ruby and Scala?
That's what CoffeeScript does. You write in a very spare and clean object-functional language, and it compiles into safe JavaScript. Other than being able to transparently call functions in the JavaScript library, you don't even have to think about JavaScript (well, except when debugging, but even that might be a temporary issue).
The CoffeeScript site is very well done; it has a nice introduction and there are numerous resources including a screencast introduction; there was also a recent presentation at JavaZone which is quite good and not linked from the CoffeeScript site.
My favorite book so far is the free, online Little Book on CoffeeScript (except for the last chapter, which I found muddied the waters). I've also been reading CoffeeScript: Accelerated JavaScript Development which I like -- the voice makes for pleasant reading -- but which is slightly odd in places, nonetheless quite useful. There's even a chapter on using CoffeeScript with jQuery which I found helpful (and another indication that the combination of the two is the future of UI).
Although I will let the jQuery and CoffeeScript resources cited above be your full introduction to the language, I'll show you an example here that is one I tend to create whenever exploring a new UI development system; it's sort of my "hello, world" for UI.
I like to see what it takes to create a grid of colored boxes and then randomly change those colors. This is by no means a perfect exploration of a UI system, but it gives you a good feel about what it's like to develop with. Considering the difficult experience I had with JavaScript years ago, CoffeeScript + jQuery is a delight to use. Indeed, even considering all the UI libraries I've looked at over the years, this system is certainly one of the best, especially when you take into account the ever-expanding ocean of jQuery plugins.
jQuery works by hooking into your HTML and modifying it. This "hook" can be virtually anything from tag types to styles to individual identifiers. To start with, we'll use the id "board"of a single paragraph as our hook:
<!doctype html> <html> <head> <title>CoffeeScript and jQuery Make a Color Grid</title> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="grid.js"></script> </head> <body> <p id="board" align="center"></p> </body> </html>
Note the inclusion of jquery.js, which is all you need do to add jQuery. The grid.js is the JavaScript file that will be generated by our CoffeeScript code. So all the browser sees is HTML and JavaScript.
Let's create the CoffeeScript in pieces. We're going to create a table filled with rows of cells of blocks of color. Here's a CoffeeScript function to create one of those cells:
cell = (row, col) -> "<td id='#{row}X#{col}' style='border-style:solid;border-width:8px;'></td>"
Like JavaScript, everything in CoffeeScript is a variable -- including a function. To make cell a function, we assign it to a function. A function is defined as an argument list in parentheses followed by an arrow, followed by the function definition. Basically, all functions are defined as anonymous functions, and we can choose to assign them to variables if we want. So here, cell is a function that takes two arguments.
Like Python, blocks of code are determined by indentation, and the de facto standard indent size in CoffeeScript is 2.
Like Scala, the last expression in a function becomes the return value. So here, we're returning a string. Note the #{row} and #{col}; within a double-quoted string; these expressions substitute the row and col variables into the resulting string. This becomes the unique id for that cell, which we'll use later to discover and manipulate that cell using jQuery.
You can also see that I have not established the color of the table cell yet. We'll do that later, also using jQuery.
Now let's create a row of these cells:
row = (ncols, row) -> '<tr>' + (cell(row, col) for col in [0..ncols]).join('') + "</tr>\n"
The parenthesized expression is a comprehension, just like in Python. The square brackets create a list, and the .. produces a range. Once the list of cells is created, it is joined together using the JavaScript join() function -- note how transparent it is for CoffeeScript to call JavaScript functions, just like Scala calling Java functions.
Finally, the whole table:
table = (nrows, ncols) -> '<table>\n' + (row(ncols, n) for n in [0..nrows]).join('') + '</table>'
This will be inserted into the paragraph in our HTML.
Now we want to create a random RGB color:
randomRGBColor = -> val = -> Math.floor(Math.random()*255) "rgb(" + val() + "," + val() + "," + val() + ")"
If you have no arguments for your function, you can just leave out the parentheses for the argument list. Note that val is a nested function, and that one-line functions just put the code on the same line as the arrow.
The randomize function steps through all the cells and change the CSS border-color for each one using jQuery:
randomize = (nrows, ncols) -> for r in [0..nrows] for c in [0..ncols] $('#' + "#{r}X#{c}").css("border-color", randomRGBColor()) setTimeout (-> randomize nrows, ncols), 1000
The $ calls jQuery, and the expression in parentheses right afterward tells jQuery what we're looking for. Here, the initial # means we're looking for an id (a leading . would mean a class name, and there are others). Once we find the component with that id, we use the jQuery css() method to change the border-color to a randomly-selected color. Finally, we use JavaScript's setTimeout() function to call this function again after 1 second.
Every program needs a main(). In jQuery, this must be attached to the point in the lifecycle after the page is loaded and is ready, so that jQuery can find the components you're looking for. In CoffeeScript, your main() looks like: $ ->:
$ -> rows = 30; cols = 60 $("#board").html(table rows, cols) randomize rows, cols
Semicolons are normally unnecessary in CoffeeScript because it recognizes line breaks after complete expressions to be the end of that expression. If you want to put more than one expression on a line, you separate them with semicolons.
The $("#board") tells jQuery to find any and all components with that id (in our HTML, there's only one). The jQuery html() method inserts its argument as HTML. The argument is a call to our table() function, but note that -- like Ruby and Scala -- we don't need to use parentheses around the arguments.
Once the table has been inserted, we call randomize() and the flashy blinking colors begin!
While developing, you can tell the CoffeeScript compiler to run in the background and compile your code every time you save it. In my case, all the above code was in a file called grid.coffee so the command-line for continuous compilation is:
coffee -w -c grid.coffee
For monitoring and debugging, the docs tell you to install FireBug on FireFox, but I discovered that the Chrome browser has very nice debugging built-in: select the wrench on the right side, then tools, then JavaScript Console. Note that all debugging messages will refer to the generated JavaScript rather than the CoffeeScript source, so you must at least be comfortable with JavaScript.
As incredible as the CoffeeScript/jQuery combination is, there are limitations.
Programming environments. These are not like FlexBuilder (yet), but I suspect we might see them -- perhaps even from Adobe. I'm used to being on the bleeding edge, so I just installed CoffeeScript-mode for emacs.
Debugging. As noted, debugging tools work only with the generated JavaScript, and your primary way of communicating program status is with console.log. Again, I'm used to the bleeding edge so I didn't have any complaints about the tools at hand.
The combination of CoffeeScript and jQuery looks like a juggernaut to me. They solve so many of the previous problems that it's breathtaking. I don't see jQuery being unseated anytime soon; it will just continue to grow. I really like CoffeeScript, but someone could conceivably come along with a much better language and unseat that sometime in the future. But for now, my UI issues are resolved.
Have an opinion? Readers have already posted 4 comments about this weblog entry. Why not add yours?
If you'd like to be notified whenever Bruce Eckel adds a new entry to his weblog, subscribe to his RSS feed.
Bruce Eckel (www.BruceEckel.com) provides development assistance in Python with user interfaces in Flex. He is the author of Thinking in Java (Prentice-Hall, 1998, 2nd Edition, 2000, 3rd Edition, 2003, 4th Edition, 2005), the Hands-On Java Seminar CD ROM (available on the Web site), Thinking in C++ (PH 1995; 2nd edition 2000, Volume 2 with Chuck Allison, 2003), C++ Inside & Out (Osborne/McGraw-Hill 1993), among others. He's given hundreds of presentations throughout the world, published over 150 articles in numerous magazines, was a founding member of the ANSI/ISO C++ committee and speaks regularly at conferences. |
Sponsored Links
|