Tuesday September 23, 2008Jason Harwig
The most popular entry I've written at Near Infinity has been the JavaScript Particle Engine. It had limitations because I used transparent images and only made one color &mdash black. I recreated the fire demo for a talk &mdash Advanced Web Graphics with Canvas &mdash that I gave at the Rich Web Experience. I'll post the slides, sample code, and some more demos in upcoming entries.
The code only took an hour to port from images to canvas, and had a number of benefits:
As with all these prototypes I don't spend time porting to IE, but it would work. It would be slower and vml doesn't draw radial gradients correctly so it wouldn't look as good.
demo
I was reading a blog entry at Web Reflection that outlined some obscure solutions to common JavaScript patterns.
I thought that entry was interesting, but I'm not sure I'd use them because of code readability and maintenance. It did get me thinking of some other ways to obscure simple tasks.
a better ternary?
Have a co-worker that thinks ternary expressions are ugly? Offer them this alternative:
var saveFunc = isNew ? insert : update; // becomes... var saveFunc = [update, insert][+isNew];
Looks a little crazy, huh? It works because a '+' or '-' before a boolean converts the boolean to a one or zero depending on its truthiness. The one or zero is accessing that element of the array. They'll be begging for ternary after that.
I think I might actually use that that syntax in situations where I need to add one depending on a boolean:
var version = x + (+shouldIncrement); var version = x + (-shouldNotIncrement);
throw out parseInt
Converting a string to a number is often done with parseInt. There are some gotchas that many people fall into in that the second parameter to parseInt is not required, but should be. For instance:
var x = parseInt("08");
// x is 0, because it assumes octal (base 8)
var x = parseInt("08", 10); // force base 10
// x is 8
// an alternative
var x = +"08";
// x is 8
// Negation works also
var x = -"08";
// x is -8
Use them wisely, or preferably never.
Wouldn't it be cool if you could do this?
@variables {
NEAR_INFINITY_ORANGE: #C96522;
}
div.header {
background-color: var(NEAR_INFINITY_ORANGE);
}
or do property transitions like this:
div {
opacity: 0;
transition: opacity 1s linear;
}
div:hover {
opacity: 1;
}
or do transformations on elements?
#downloadLink {
transform: rotate(10deg)
}
... well it's coming, and in some cases already here. The last two are already working in Safari 3.1 and there is a spec for CSS variables.
Hopefully we are past those days where a spec is released, but no one could use it until 5 years later. Ajax took ~6 years for crying out loud.
twitter: jharwig
The web community has been buzzing about the new Ajax server, Jaxer, from Aptana. If you haven't heard see John's, or Dion's Ajaxian posts about it.
Now, overall, I am really excited about the future in this project. The problem I had is all their examples use synchronous XMLHttpRequests. We already know why this is unfriendly to users.
Here is a shortened example from Aptana:
Here the call to getName() must return the name, so it runs synchronously. Jaxer provides a getNameAsync() method that accepts a callback (and uses an async XMLHttpRequest call) but it's hidden deep in a technical FAQ page.
Obviously the synchronous code reads better, but until JavaScript has some kind of continuation support to make async calls look synchronous, [functionName]Async should be the only -- or at least default -- means of server communication. Otherwise all Jaxer apps will seem perceivably slow to users, not to mention preventing all other browser windows from responding while requests are active.
I gave a JavaScript security talk last month, and one of the topics was HTML filtering. I gave examples of how MySpace tried to filter executable code, while still allowing HTML tags for formatting. MySpace, of course, failed to foresee every attack vector, and the Samy worm was born.
HTML filtering was never recommended because it was so difficult to get right, and with no proven libraries, trying to build a solution would almost certainly contain security holes. Thanks to Arshan Dabirsiaghi we finally have something to use. He has created the OWASP AntiSamy project to easily sanitize HTML input. AntiSamy is currently implemented as a Java 1.5 compatible library, but there are plans to support other platforms.
Here's a sample usage...
AntiSamy sanitizer = new AntiSamy();
CleanResults results = sanitizer.scan(request.getParameter("html"));
String html = results.getCleanHTML();
if (!results.getErrorMessages().isEmpty()) {
log.warn("Input contains errors");
}
I spoke at the Reston, VA No Fluff Just Stuff conference again this past weekend. The talk was on JavaScript security covering topics including:
Here are the slides...
This is a short tip that I found useful for testing complex JavaScript objects using crosscheck. For more information on crosscheck see my article on JavaScript Unit Testing with Crosscheck.
Testing instance methods can be a pain if the functions use instance variables and the object is heavyweight. In my case the constructor did a lot with the DOM that I didn't want to mock. Instead of invoking the function through an instance of an object, I called it statically.
Function.call
"call" is a built in function on the function prototype in JavaScript -- just a little confusing :). Using function.call we can invoke functions and pass in an object with properties that the function depends on. Here is an example documentation of the function, and an example use case. parameters the objects to pass to the function */ Function.prototype.call(instance, parameters...); var x = { message: 'Hello World' }; var hello_function = function(name) { alert(this.message + ", " + name); } hello_function.call(x, 'jason');
Crosscheck and call
To test an instance function in crosscheck, set the object to values you want the function to get and use call to invoke it. Here is an example function and test.
Keep increasing that coverage!
Here we are, a couple years since Ajax was coined, JavaScript has become a language that people actually respect. The code being written now is better than ever before. Object-orientation, name-spacing, object detection, and correct scoping are prevalent now. The libraries available (prototype, jquery, yui, dojo) are very well written. What is the next step to improve code quality? If you want my opinion, it's Testing. Otherwise, here's the door. :)
Many experts that advocate testing bring up selenium. While I think selenium is great, it is a functional test tool. All you are really testing is that you scripts aren't generating errors and working at a basic level. Unit testing ensures that your code is correct, i.e. it does what you think it should.
So, how do you unit test JavaScript? I've had good luck with crosscheck. Here's a synopsis from thefrontside.net...
Crosscheck tests look like this:
Now we need a js code coverage tool to show how badly we are doing in respect to JavaScript testing. JavaScript Coverage Validator is something that I'll have to try.
Starting a backup routine is hard. I wanted a backup solution that did the following:
The key for me is incremental checkpoint backups, and by than I mean that every time the backup runs it creates a folder that only contains the changes since the last backup. See image on right, and how the file shares an inode. We can do one better using unix hard links to show all files, while still not using any more space. Read about hard links on wikipedia.
The unix utility rsync that comes with OS X 10.4 solves bullets 2-4 according to the man page. But, in practice, I could never get the checkpoints working correctly with "rsync --link-dest". Apparently that parameter doesn't always work. I tested it by running some test backups and checking the inode of the files using "ls -li". If a file doesn't change across backups it should share an inode number.
After more digging on the net I ran across rsnapshot, which is a perl front-end to rsync. It can make incremental checkpoints without link-dest. This blog shows some steps to getting rsnapshot installed on OS X. I'm going to augment those steps because I didn't want to install darwinports or fink, and I wanted to use launchd instead of cron.
Download and Installation
First, go to rsnapshot.org and download the "Generic UNIX" gzip, rsnapshot-1.3.0.tar.gz. Now, open terminal and type the following:
Configuration
See this blog and the rsnapshot docs for the options to specify in the config file. The file is very well documented. You can download my configuration files here. At the minimum, you need to change the snapshot root and the backup points.
Automation
The blog uses crontab, but Mac OS X 10.4 deprecated cron for launchd. For information on launchd, see Apple's documentation. My configuration is included in the resources zip below. It goes in /Library/LaunchDaemons. If you want other intervals besides daily, make sure they are uncommented in the rsnapshot.conf and create new launchd plist's for them. Once the launch configuration is complete, load the configuration with the launchctl command or just restart:
Testing
For initial testing you might want to change your backup points to be smaller, otherwise this could take a while. When your ready, run a backup by typing:
This will create a daily.0 folder in your snapshot root directory. If you run the command again, the daily.0 will be renamed to daily.1 and daily.0 will represent the new backup. You can verify that inodes of files haven't changed using this command in your snapshots directory:
That's it, now I just need to get these offsite, for a solid backup solution. Rsnapshot supports using ssh to backup to a remote server. See the rsnapshot documentation for more information.
Resources
Download my launchd and rsnapshot configuration files.
It seems that Encytemedia was successful in their "Call for Prototype Documentation" blog posted in the old year.
The site lives at prototypejs.org and should help new and experienced users alike master the popular JavaScript library.
Features
Good work guys!
Looks like Joe Hewitt has been busy.
Firebug now has it's own site at getfirebug.com. The new site shows the features for Firebug 1.0 which seem like a giant leap in functionality from the current 0.4.1. My favorites look to be the new profiler and the network activity view (shown right).
The catch? According to Hewitt's blog, it might not be free. I know I would pay $15-$25, what about you?
Javascript particle Engine
I was at the No Fluff Just Stuff Software Symposium in Reston, VA this past weekend and had some time in between sessions to work on something. As most of the people I work with know, I rarely code things that might actually be useful to someone in my spare time. So, I had no reason to attempt to rationalize the use for a particle engine in Javascript.
I think I've written a particle engine in almost every language I've used for an extended period of time. This includes python, java, objective-c, and c. What's surprising is that it has taken me this long to write a particle engine in the language I probably spend the most time coding in -- Javascript.
By the way, this is probably the worst particle engine ever created (TM), but it is written in Javascript, so give me a break. It doesn't support colors yet as I couldn't think of an efficient way to change the color of a png. I've only tested it in Firefox and Safari because I'm on a Powerbook. It's also pretty slow, in that it can handle only a dozen or so particles.
Let me know what you think!
features
demo
html configuration
download
Download the javascript particle emitter source.Here's an interesting bug in Internet Explorer I ran across today:
main.html
MAIN CONTENT
[ iframe.html ]iframe.html
... Some breaks ...When main.html is opened in Internet Explorer 6 (try it), the iframe doesn't move to the anchor, instead it refreshes itself with the contents of it's containing html page -- main.html. Huh? If we change set window.location to "#here" instead of instantiating a new String object, it works as expected (try it). What is going on here? Let us try to break down the line in question.
Javascript's string primitives and String Objects
Javascript provides both string primitives and String objects1. A string object is created by new String(""), whereas a primitive is declared by quotes. The object contains methods like charAt and properties like length and is automatically instantiated anonymously if you write something like: "hello world!".length.
window.location
The location object is special. Isn't it? You can set it to a string, or any of it's properties. Could IE be confused when objects are being passed in? Maybe confusing a string object with a location object?
Anyone have any other ideas?
Of, course, the better way to go to an anchor on the current page is setting the hash property of the location object. Using a string primitive versus a String object both work equally well. Here's an example.
the waiting game
No matter what apple says about Java development on the Mac, I always hated the waiting game before I could use some new Java API. First, it was Java 5 Tiger, which because apple ports it themselves to the platform, lagged considerably behind the Sun release. Then, it was Java3D and the JAI API. Even now, the Java3D API on OSX is at 1.3. I'm just glad that the JOGL and Java3d folks found a way to bypass Apple's porting process this time with Java3D 1.5.
Java3D is currently at 1.4.0 stable and has a 1.5 dev version out. The key to all of this is that the 1.5 branch includes the ability to use JOGL to bind the Java3D API to the native OpenGL implementation. What does this provide? Well, since JOGL is already ported to OSX, we can install Java3D 1.5 and JOGL and upgrade our outdated Java3D!
how to do it
Prerequisites
Procedure
Have fun with all the new features!
The problem..
If I had been allocated one Firefox extension to use, without hesitation it would be Joe Hewitt's Firebug. But, eventually, I have to test my code in IE (and Safari1), and need to debug some DOM or css scripting. Many times I would use the url field to execute Javascript in the page using this method...
Wrapping the code in a function will prevent variable name collisions. The problem is that this method can get messy and time consuming when trying to inspect elements nested deep within the DOM.
An answer?
I created a bookmarklet that allows you to inspect DOM elements, just like Firebug2. Using a bookmarklet allows it to run in any javascript browser, including Firefox. After inspection, a console can be used to modify and query the object. How does it work? The bookmarklet is just a stub that loads the external javascript file3. It adds a click and mouseover handler to the document body object. The mouseover handler adds a window status message with the highlighted DOM tree, and the click attribute opens the inspector.
The inspector has a console with the variable clicked_element pointing to the element. Common attributes like id, class and innerHTML can be edited live. All other attributes can be viewed (or changed using the console) and the computed style is also available.
Download
Save the bookmarklet archive, or try it out on this page. (You can also bookmark this link directly)
Screenshots
Todo
1Safari webkit nightlies include a DOM inspector, but no console for easy manipulation.
2I know this is hardly a port of firebug, but the title "DOM/CSS Javascript inspector bookmarklet for IE/Safari" wasn't as catchy.
3IE 6 has huge limitation in that the url is only parsed to 512 characters. The external javascript is also much easier to maintain.


