jMar"s Blog DevSmash Developer Portal

Thursday, June 26, 2008

Kwicks 1.5.1 Released!!!111!!


So it turns out that people didn't really like the "Invalid Argument" error that Kwicks 1.5 was throwing in IE7+.

Kwicks 1.5.1 fixes the bug and is ready for download.

Once again, I would like to thank Rúbel Mujica for his role in identifying and fixing the bug. I would also like to thank everyone else who has shown an interest in the Kwicks plugin and for all of your invaluable input!

Tuesday, June 17, 2008

Kwicks 1.5 Released!

Kwicks 1.5

Well I'm happy to announce that I have finally wrapped up the v1.5 update to the Kwicks plugin. Kwicks 1.5 builds upon the original release in several big ways - here is a summary of what's different:

  • Vertical Mode!

    This was a common request, so there was no way I could leave it out of this release.

  • Min vs. Max

    The previous release required developers to specify the "max" width of the active kwick. As of v1.5, developers may now opt to specify the width/height of all of all of the non-active kwicks instead. This feature doesn't really add new functionality, but is merely offered as a convenience.

  • Sticky Mode

    When sticky mode is enabled, one kwick will always be open. This allows for more of an "accordion" type experience.

  • Custom Trigger Event

    Kwicks 1.5 lets you specify the trigger event for the animation. The default is still 'mouseover', but many users had wanted to use 'click' in instead.

  • Smoother Animations

    This release I did some refactoring of the code behind the animations. Several calculations were moved outside of the inner loops allowing for a less tasking, and consequently smoother, animation.

  • Packed Script

    While this release still comes with fully commented and readable code, it also comes with a packed version which is far better for production use. The new packed version is only 2.4 KB, which is actually smaller than the original release.

All in all this is a huge addition to the original version - many of the excellent suggestions I have received were addressed, and I hope that you will find the added flexibility more helpful than confusing. I always believe simplicity is key, so I have tried to keep that in mind as the new features were added. So what are you waiting for? Go check it out!

Wednesday, May 28, 2008

A "Dirty" Photoshop Tutorial

Well, despite being a long time user of Photoshop, I've never sat down and attempted to make a tutorial. I realize that the web is chock full of text effects for Photoshop, but this is a particular look that I haven't seen described before. During the tutorial I share a couple of the hot-keys that I employ most often, so I'll apologize to the Mac users for only providing the Windows version (where they differ). From what I understand, they're all pretty close... so that's that. Let's dig in...

Create a New Project

Press Ctrl + 'N' to open a dialog for creating a new project. Normally I work at higher resolutions, but for the sake of this tutorial I chose 640px by 480px.

Create a Background

Something simple here will do. I set my foreground and background colors to darker shades of blue (#2C326E and #2D304A respectively). Pressing Shift + 'G' will let you toggle between your gradient and bucket tools. Using the gradient tool, click and drag your mouse from the upper left to the bottom right corners of the canvas. Your canvas should now look like this:

Create Dirt Layer

Press Ctrl + Alt + Shift + 'N' to create a new layer. We're going to create a new gradient just like we did in the step above, but this time, select two different shades of brown. I chose #A2702F and #7F561E for the foreground and background respectively. Your canvas should now look like this:

Add Noise to Dirt Layer

Next, in order to simulate the gritty nature of dirt, we're going to add a Noise filter to our dirt layer. Click Filter > Noise > Add Noise...

I used the options shown in the following image:

Add Text

Next we want to add some text. The exact font you use isn't important, although I have found that "round" works better than "sharp" for this effect. Also, you will want the font to be sufficiently thick (i.e., don't use Arial Narrow). I chose a font called "Elephant" and used 170pt for the size. The color is of no consequence here.

Create Mask from Text

This step requires performing the following actions:

  • Hide the text layer by clicking on the corresponding "eye" symbol.
  • Select the dirt layer.
  • Click the 'T' on the text layer while holding the Ctrl key.
  • You should now see that the outline of the text is selected.
  • Click the "Add Layer Mask" button shown below:

Your canvas should now look like this:

Add Loose Grains of Dirt

This is where we want to start adding in the random grains of dirt to make this look more natural. This step requires performing the following actions:

  • Select the brush tool (press 'B').
  • Choose a grainy looking brush. I chose one of the default brushes as shown below:
  • Now select the dirt layer's mask by clicking on the layer mask thumbnail, as shown below:
  • Ensure that your foreground color is white.
  • Now you need to rely on your artistic eye a bit and click around in various places to reveal the dirt texture behind the mask. Note that you don't want to drag the brush while clicking, since streaks will not look natural. Mine ended up looking like this:

  • The scattered dirt effect doesn't look quite right, so now we're going to switch the foreground color to black and selectively remove some of the dirt. Mine ended up looking like this:

Add Depth to the Dirt

The layer mask is finished now, but the dirt looks too flat. Double click on the dirt layer to bring up the Layer Style dialog. Make sure that "Layer Mask Hides Effects" is not checked. Now add a drop shadow with the following properties:

For the color, I used #3A2900.

It's getting closer, but let's add a gradient overlay to give the light a little more "play" on the dirt. I used the following properties:

Smooth Dirt

Some of you may wish to stop here, but I found that the Noise filter had left the dirt looking a little too grainy for the look I was after. To smooth it out a bit, I unlinked the layer mask from the dirt layer by clicking the unlink mask button...

...and then I applied a very light Gaussian Blur (Filter > Blur > Gaussian Blur...) to the dirt layer:

That's it! Here's the finished effect:

Mixing the random characteristics of scattered dirt with purposeful lettering can be tricky, but I feel this effect does a decent job of providing just that. If you have any suggestions on how to improve the realism, please comment!

Friday, May 23, 2008

How to Fix the Blogger Comment System

I'll be honest - I really like Blogger. Despite the fact that nearly every co-blogger I know has urged me to give Wordpress a try, I'm still (mostly) satisfied with what I've got. I serve static pages and other content myself, and let Google worry about hosting the blogs that account for over 90% of my total traffic. However, there is one thing, in my opinion, that is unforgivably lacking in Blogger: the comment system.

The comment system is so abysmal that I'm literally on the verge of creating my own message board that I can simply embed in an iframe. If I weren't so packed for time lately, you could consider it done. However, before I launch another harder-than-I-thought-at-first project, let me share with you the features that I believe, for the most part, any blogging platform should afford.

So here they are, in no particular order:

  1. Unique Styling for Author Comments

    This one seems obvious to me. Every other message board on the planet does this, yet Blogger currently offers no CSS accessible way to distinguish an author comment from a user comment. I've previously discussed a hack method using JavaScript to accomplish author comment styling, but it's ridiculously more painful than it should be.

  2. Threaded Comments

    This one's pretty straight forward - users should have the option of replying to a particular comment, rather than being forced into a flat discussion. Tree style comment threads allow for individual conversations to be self contained.

  3. Collapsible Threads

    This feature is obviously dependent on the previous one. But assuming threaded comments were implemented, I would expect the ability to collapse a thread that I was not interested in. Think Digg...

  4. Get Rid of that Separate Comment Page!

    Why oh why am I taken to another page just to leave a comment? Can there possibly be a good explanation for this?

  5. Language/Profanity Filters

    Ya, some of us are still old fashioned like that. This would be especially appreciated in family and faith oriented blogs.

  6. WYSIWYG Editor

    Personally, I hate them - but the fact is, WYSIWYG editors are now a consumer expectation. Given the crowd that tends to follow my articles, this blog would probably benefit a lot less from this than a less code-savvy user base.

  7. Private Comments to Authors

    I'll admit that from here on out I'm probably going above and beyond what I'd consider "minimum requirements." However, being able to send private comments to the author would be a handy feature. For one, it would be a safe and convenient way to share personal contact information.

  8. Spell Check

    Since I use Firefox, I simply use the built in spell checker, but this would be helpful for visitors using other browsers. This is another example of something Digg did right...

  9. Arbitrary Thread Locks

    The author of a blog should be able to enable or disable comments on a post-by-post basis. This disable feature should have the option to actually hide all the comments, or simply disallow additional comments.

  10. Statistics

    This is probably the least crucial of all my wants, but it would be nice to see some overall statistics (e.g., average comments per post, post with most comments, etc...).

Well that's it for my list. Please feel free to add any additional ideas in the comments!

Monday, May 5, 2008

jQuery UI 1.5b4 Released

Paul Bakaus and the jQuery UI team have just released jQuery UI 1.5b4 - the last scheduled beta version before a release candidate. Along with the new beta version, the jQuery UI homepage has been given a major overhaul. While parts of the site are still under construction, it does include several functional improvements, such as a download builder and an improved demo showcase. So head on over and check it out!

Happy Cinco de Mayo!

Thursday, May 1, 2008

Why PHP and JavaScript IDE's Suck

Few things fire up an engineer faster than over generalizations, criticizing a favorite language, or attacking their favorite IDE. So I'm off to a good start. Oh ya, my mom hates that word too (sorry Mom)!

However, interestingly enough, this fact (just concede for now) is not the fault of the given language, or even the IDE developers. So who's fault is it? In truth, no ones. It's really more of a bi-product of these languages themselves (and as we'll see, many other languages (such as Perl) could be thrown into this bunch as well). In fact, the same IDE, such as Eclipse, can be outstanding with a language like Java, yet be rather disappointing when it comes to PHP.

So before we go any further, I need to lay out a tighter definition for "suck". I'll admit that it's too broad a stroke, albeit attention getting. If I had to pick one single feature that makes or breaks an IDE for me, it would be autocomplete (or Intellisense for you Visual Studio people). The frameworks and libraries that we use today are simply too big to try and remember every single class/object member, and it's just too slow to go sifting through the documentation every two minutes. Nothing speeds up my productivity like being able to press Ctrl + Space and voila - there are my options. Therefore, to me, and for the purposes of this discussion, any IDE that doesn't have autocomplete that's up to snuff, sucks.

Thus far, the languages that I've interacted with the most are Java, PHP, C#, C++, JavaScript, and I've dabbled with Object Pascal. I'd consider myself a jack-of-some, master-of-none. In the bizarre scenario where I had to put each of these languages into one of two buckets at gun point (me, not the buckets), I would divide them based on this single comparison: strongly-typed versus loosely-typed.

Interestingly enough, if I compared them based on their respective "IDE suckiness", they'd end up in the same buckets. Why is that? Well, as I've already implied, there's a strong correlation between how a language is typed, and how effectively an IDE can offer suggestions from a given context. In contrast to a loosely typed language, a strongly typed language can make some guarantees about what a variable holds.

For example, if I'm working on a Java application in Eclipse, I can use autocomplete to inspect the members of my current object, like this:

Eclipse Screenshot

Most conveniently, all of my autocomplete options are relevant to my Person object. Eclipse can do this because in Java, once I declare jMar as a Person, it now has a guarantee that jMar is and always will be a Person. This guarantee holds true for other strongly typed languages as well, which provides their respective IDE's with the same promise.

Now let's say I'm working on a PHP application in Dreamweaver. If I reproduce the equivilent Java code from above, my "autocomplete" options are really just a list of every function defined in the PHP5 documentation.

Dreamweaver Screenshot

Slightly more helpful than nothing, but it's far short of I had before - not to mention that this gives me no insight into the members of my Person class. But don't hate Dreamweaver - what else can it do? Remember - when you're coding in PHP, you're not making any guarantees as to what a variable holds.

Consider the following perfectly legal PHP code:

class FirstClass {
 ...
}

class SecondClass {
 ...
}

$foo = new FirstClass(); // $foo is now a FirstClass
$foo = new SecondClass(); // $foo is now a SecondClass
$foo = "bar"; // $foo is now a string
$foo = true; // $foo is now a boolean
$foo = 777; // $foo is now an int

No wonder the autocomplete isn't much help. And this is the exact same scenario for JavaScript, Perl, and other loosely typed languages.

I know I've personally been frustrated on numerous occasions with the apparent "lack of effort" being given to autocomplete with regards to these widely used languages; however, after pondering some of the fundamental obsticles that the IDE developers are facing, I can understand how the feature set is impacted by the target language. I suppose an article can only be so valuable without offering some sort of a solution, but just consider this a "state of affairs" on the IDE world, and thanks for reading!

Tuesday, April 22, 2008

Know Your Environment: PHP Server Module Reporter

This post was authored by David Walsh. To learn more about David, click here.

One of the unfortunate parts on my job is that I rarely get a say in the customer's hosting environment. We don't host our customers' sites so I'm usually at the mercy of whichever hosting provider the customer has contracted with. We usually try to steer our customer toward our preferred host, but most of the time the customer is reluctant to switch because they fear email issues and change in general.

Knowing the hosting environment's limitations before we begin to develop the website is a must. Imagine creating a great website and running into issues later on because the shared hosting server doesn't have a given extension installed. A nightmare!

I've created a basic PHP script that I simply FTP to the server and use to evaluate extensions on the server. I simply supply the extensions I require and the script does the rest of the work.

<?php
 /* set required extensions */
 $my_required_extensions = array(
  'gd',  //graphics library
  'xml',  //xml
  'mysql', //database
  'curl',  //networking
  'openssl', //site will need SSL
  'pecl'  //pear
 );
 natcasesort($my_required_extensions);
 
 //get loaded modules
 $loaded_extensions = get_loaded_extensions();
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
 <title><?php echo $source_article; ?> Example</title>
 <meta name="description" value="<?php echo htmlentities($meta_description); ?>" />
 <style type="text/css">
  body  { font-size:12px; }
  h2   { border-bottom:1px solid #ccc; font-weight:normal; font-size:18px; margin-bottom:5px; padding-bottom:2px; }
  p   { line-height:20px; margin-top:0; }
  .found  { background:lightgreen; padding:5px 10px; margin:0 0 10px 0; }
  .miss  { background:pink; padding:5px 10px; margin:0 0 10px 0; }
  .extra  { background:lightblue; padding:5px 10px; margin:0 0 10px 0; }
 </style>
</head>
<body>

<h1><?php echo $_SERVER['HTTP_HOST']; ?></h1>

<h2>General Information</h2>
<p>
 <strong>Server Software:</strong>  <?php echo $_SERVER['SERVER_SOFTWARE']; ?><br />
 <strong>Document Root:</strong> <?php echo $_SERVER['DOCUMENT_ROOT']; ?><br />
 <strong>PHP Version:</strong> <?php echo phpversion(); ?>
</p>

<h2>Extension Check</h2>
<?php 
 /* print out */
 //analyze results
 foreach($my_required_extensions as $ext)
 {
  if(in_array($ext,$loaded_extensions))
  {
   $matches[] = strtolower($ext);
  }
  else
  {
   $missings[] = strtolower($ext);
  }
  unset($loaded_extensions[$ext]);
 }
 //print out results
 natcasesort($matches); natcasesort($missings); natcasesort($loaded_extensions);
 foreach($matches as $match) { echo '<div class="found"><strong>',$match,'</strong> found!</div>'; }
 foreach($missings as $miss) { echo '<div class="miss"><strong>',$miss,'</strong> missing!</div>'; }
 foreach($loaded_extensions as $e) { if(!in_array($e,$matches) && !in_array($e,$missings)) { echo '<div class="extra"><strong>',$e,'</strong> is available.</div>'; } }
?><br />

</body>
</html>

The output looks as follows:

Extension Evaluator Screenshot
(click to enlarge)

If I run into the situation where a needed extension isn't there, I must decide whether to push for the customer to switch hosts or adjust the way I code the website. You'll also want to keep a copy of this on hand so that you have proof when the host changes the server and causes issues with the website. Happy coding!

David Walsh.David Walsh is a Senior Web Developer residing in Madison, WI. He spends most of his day getting a monitor tan coding PHP, CSS, MooTools, and XHTML. When not tinkering with the newest version of Moo, David uses soccer, Rock Band, and movies to dull his coding pains.

Friday, April 18, 2008

Add Hover Class to Anything in jQuery

Well I've been feeling a little guilty for the relative sparsity of my posts lately (not that I don't have a good excuse or two), but I wanted to at least get on here and share a quick little tip.

One of the most fundamental "effects" employed by CSS designers is that of indicating when an anchor tag is being "hovered". Virtually every CSS file you encounter will contain something like the following:

a:link {
 /* default styles for anchors */
}

a:hover {
 /* styles for hovered anchors */
}

Often times, however, this same effect is desirable for non-anchor elements as well. For example, in my applications, I like to visually indicate anything that can be the target of an onclick event - and practically speaking, that's not always an anchor. The problem is that :hover is not a reliable cross-browser pseudo-selector on non-anchor elements. Can anyone guess which clIEnt I'm talking about?

Well fret not, cause we have JavaScript to the rescue. In this particular example, as usual, I'm using jQuery to make life easy. Since we can't rely on :hover, we're going to dynamically add a class of hover via JavaScript. The code to do this is remarkably simple:

$('*').hover(
 function() {
  $(this).addClass('hover');
 },
 function() {
  $(this).removeClass('hover');
 }
);

Now let's say you want to style a div with class iHoverable differently when it's being hovered. You can simply add the following rule to your style sheet:

.iHoverable {
 /* normal styles for this element */
}
.iHoverable.hover {
 /* styles for hover effect */
}

That's almost it - just a quick note from a practicality standpoint. I don't really recommend using $('*').hover(...) from the code above. If you already know that you only need to style hovers for elements of class iHoverable, then it would be more efficient to simply write $('.iHoverable').hover(...)

Kapeesh? Ok, now that's it.

OOPS!

It has come to my attention that this post is remarkably similar to a previous post by Karl Swedburg from over a year ago. My bad!

Thursday, April 17, 2008

Load Your Static Content the Dynamic Way

David Walsh was kind enough to let me guest author an article on his blog. Check it out!

Saturday, April 12, 2008

Introducing: Kwicks for jQuery

Well despite the underwhelming response I got from my teaser post earlier in the week, I went ahead and wrapped things up. For those of you jQuery fans who have been ashamedly drooling over the perfectly simple Kwicks effect for Mootools, now you can have it too.

The Kwicks for jQuery plugin, documentation, and examples can be found at the Kwicks for jQuery Homepage.

So far I've only been able to test it in IE6+, FF2+, Safari 3 for Windows, and Opera 9. If you encounter any issues let me know!

Tuesday, April 8, 2008

Spoiler Alert!

So I might have over dramatized this post a little - but I wanted to let you all know what I've been working on the last couple days...

Kwicks Teaser

Ya... totally awesome. I really just wanted to post this so that I could hear any special requests while I wrap things up. I really love the effect of this menu (see the Mootools home page), but I haven't actually used the Mootools original before. Therefore if there are any annoyances - I don't know what they are. The options that it currently supports are maxWidth, spacing, duration, and easing. If there's anything else you'd like to have control over, let me know now!

Thursday, April 3, 2008

Big Regex Improvements for Firefox 3 Beta 5

Having just posted my latest project, Asciible, that relies heavily (well, entirely) on client-side regular expressions, I've been paying closer attention to efficiency concerns. I don't know if I'd really consider myself to be a Firefox "fan boy", but it is my browser of choice, and I have to admit that I was surprised to find that IE7 was kicking FF2's butt when it came to executing String.replace().

To give you a real world context for my tests, Asciible simply searches through a text input and replaces special characters with their ASCII equivalents. Even all the custom options rely solely on simple String.replace()'s. So in fairness, be aware that this limited test does not represent an overall analysis of the regular expression engine. With that said, in this limited context IE was taking about 10% of the time it was taking Firefox to complete. I was even able to achieve nearly the same efficiency in FF2 by using a simple for loop and a character hash table - yuck.

After noticing this, I went and downloaded Firefox 3, Beta 4 and ran my tests again. I was disappointed to find only marginal improvements.

So time advances until earlier today when I was taking a look at the release notes for Firefox 3 Beta 5, and I couldn't help but notice they were touting some major performance improvements - specifically to the JavaScript engine. So with curiosity in hand I downloaded, installed, and ran my tests again. To spare you the suspense - no, Firefox did not put IE to shame, and in truth it was still the slower of the two. However it did show BIG improvements - and I'm happy to see that the regular expression engine has been given some serious attention. All in all, FF3 Beta 5 was completing the test in less than half the time it was taking FF2. For visualization purposes:

String.replace() comparison for IE7, FF2, and FF3 Beta 5

This is good news, especially since FF3 is still in beta. There's no guarantee that there will be further improvements in the final release, but the optimizations thus far are already outstanding, and certainly enough to leave me with my fingers crossed.

The Slashdot Effect

I suppose this just puts me in a long list of gratefuls to the slashdot community - but I wanted to give an overdue "thank you" to everyone who voted and put my Web 2.0, Meet JavaScript 2.0 article on the front page. Not that you haven't seen 100 such graphs before, but just in case you wanted to see how you utterly destroyed my traffic curve:

The Slashdot Effect

Incidentally, the same article made the front page of Reddit as well. The amount of traffic from Reddit was approximately 10% of that from Slashdot, but thanks to you Reddit folks none-the-less!

Tuesday, April 1, 2008

Introducing: Asciible

AsciibleWell, I've been silent for a little while - but I haven't been lazy! I've been a little slammed for time as of late, but I do have something new to to introduce: Asciible. As far as naming goes, Asciible barely edged out "Ascii Jeaves" - but it's never too late to go back...

In a nutshell, Asciible does all your ascii encoding for you. This obviously isn't the first utility to offer this service, but I have tried to make it the fastest and most flexible. Give it a whirl and let me know what you think!

Tuesday, March 18, 2008

Web 2.0, Meet JavaScript 2.0

Well I suppose it's an undeniable fact about us programmer-types - every now and then we just can't help but get excited about something really nerdy. For me right now, that is definitely JavaScript 2.0. I was just taking a look at the proposed specifications and I am really, truly excited about what we have coming.

I suppose it's important to note that these new features are tentative. The specifications documentation for JavaScript 2.0, ECMAScript Edition 4, is currently being developed by TC39. Although it is still a work in progress, an overview of what has currently been proposed can be found here (PDF). As the team expects to have completed the specifications by late fall of this year, we can expect that most of these awesome improvements will remain in the final version.

So without further delay, here's just a few of the many, many upgrades coming JavaScript 2.0's way:

OOP!

Had to start with this one - it's so big it had to be first. Introducing actual classes and interfaces into the language is likely the most radical change that will come with JavaScript 2.0. Technically speaking, OOP will be nothing new for JavaScript. JavaScript already has objects and even offers full support for inheritance through the prototype chain - however, prototypal inheritance in JavaScript is tricky business and can often produce unexpected results (especially for those accustomed to classical inheritance in languages such as Java and C#).

Not only is JavaScript introducing classes into the language, is is also doing away with primitives altogether. Null and undefined will be the only not true objects in JavaScript 2.0. Duly, classes such as boolean and string will provide wrapper classes for the sake of backwards compatibility.

As far as creating and instantiating a basic "class" goes, the process will be quite similar to using a constructor function, as in earlier versions of JavaScript. Consider the following examples:

/* JavaScript 1.x "Class" Definition*/
function Foo() {
 this.a = "a";
 this.b = "b";
}
var myFoo = new Foo(); // class instantiation

/* JavaScript 2.0 Class Definition */
class Bar {
 this.a = "a";
 this.b = "b";
}
var myBar = new Bar(); // class instantiation

That alone hardy seems worth the overhaul, but classes will provide far more flexibility through its many designators and directives (final, dynamic, extends, implements, etc.). Also note that constructor functions can be changed, whereas classes will be bound as constants, and therefore cannot be changed.

Object Oriented Programming has done to programming what relational databases did to persistence - it has dominated. I can't think of a single thing that I would rather see in JavaScript 2.0 than exactly this.

Compile Time Type Checking

JavaScript 2.0 components can request to be compiled in strict mode. This will test the integrity of several key aspects before execution. A partial list of these checks includes:

  • Static type checking
  • Verification that referenced names are known
  • Checks for illegal assignments to constants
  • Insures that comparisons are only made between valid types

Did I Say Constants?

I sure did. For such an obvious directive, constants have been a long time in coming. Previously JavaScript developers have had to use naming conventions to protect their constants, but that is no longer the case in JavaScript 2.0.

/* JavaScript 1.x constant */
var FOO = 'bar';  // look, I'm all upper cases, so pretty please don't change me

/* JavaScript 2.0 constant */
const FOO = 'bar'; // go ahead, try me...

It may take some time to realize some of the side effects of this change, however, since the constant directive will now be applied to some of the existing core JavaScript objects (such as the pointer to an object's prototype).

Operator Overloading

Cause I am, whatever you say I am, if I wasn't, then why would I... never mind. Misuse it, abuse it, do whatever you want with it. Operators are now whatever you want.

Not Null ("!") Operator

Nullability is a concept that is familiar to anyone who's worked with databases, hibernate annotations in Java, or a whole host of other technologies. In short, it allows you to specify whether an entity can be null or not. Consider the following example:

class Person! {
 ...
}
var x = new Person();

var x = null; // throws error

I'll be honest and admit that I wasn't sure if the error gets thrown on assignment, or when you attempt to read. For now, examples in the documentation are sparse, but either way this will be a handy feature. The mechanism that makes this new operator possible is union types (also new). I won't be delving into those in this article, but they would definitely be worth reading up on at the original source.

Real Namespaces

JavaScript developers have long been implementing namespaces by stuffing everything into a single global object. While this is not a bad convention (and it's much better than cluttering the global namespace), the reality is that it abuses the purpose of objects for the sake of simulating pseudo-namespaces. Well, have a guilty conscience no more, because now you have real bonafide namespaces that are actually made for being, well, namespaces.

Program Units

This is a simple addition, but to me it yields great benefits. Program units allow you to bundle up "program fragments" that don't need to be loaded until requested. This ability has all sorts of potential, not excluding bandwidth optimization.

Perhaps more significant, though, this is also a big step towards providing structured, reusable code libraries. Since the units that you reference will be loaded at most once, you now have a mechanism for maintaining elegant code libraries. Consider the following example:

use unit Person "http://mysite/library/classes/Person";
use unit DisplayUtil "http://mysite/library/utils/DisplayUtil";

var bob = new Person();
document.writeln(DisplayUtil.display(bob));

Even in this short, fanciful example you can see how your code can start to take on a highly organized and logical structure - much like many of the server side languages you may have worked with. Personally, I think this is one of the strongest improvements found in the specifications.

Conclusion

Well, needless to say, JavaScript 2.0 is shaping up to be a devastatingly awesome improvement. The specifications go on for about 40 pages of size 12 font, so I'm not even going to try and provide a complete overview. But as I've said, everything I've mentioned above can be found in the proposed language overview (PDF) - and there's several more goodies to be found in there as well. Thanks for reading!

Friday, March 14, 2008

Understanding Loose Typing in JavaScript

For many front end developers, JavaScript was their first taste of a scripting and/or interpretive language. To these developers, the concept and implications of loosely typed variables may be second nature. However, the explosive growth in the demand for Web 2.0-ish applications has resulted in a growing number of back end developers that have had to dip their feet into pool of client side technologies. Many of these developers are coming from a background in strongly typed languages, such as C# and Java, and are unfamiliar with both the freedom and the potential pitfalls involved in working with loosely typed variables.

Since the concept of loose typing is so fundamental to scripting in JavaScript, an understanding of it is essential. This article is a top level discussion of loose typing in JavaScript. Since there may be subtle differences in loose typing from language to language, let me constrain this discussion to the context of JavaScript. OK, let's dig in...

What is Loose Typing?

Well, this seems like a good place to start. It is important to understand both what loose typing is, and what loose typing is not. Loose typing means that variables are declared without a type. This is in contrast to strongly typed languages that require typed declarations. Consider the following examples:

/* JavaScript Example (loose typing) */
var a = 13; // Number declaration
var b = "thirteen"; // String declaration

/* Java Example (strong typing) */
int a = 13; // int declaration
String b = "thirteen"; // String declaration

Notice that in the JavaScript example, both a and b are declared as type var. Please note, however, that this does not mean that they do not have a type, or even that they are of type "var". Variables in JavaScript are typed, but that type is determined internally. In the above example, var a will be type Number and var b will be type String. These are two out of the three primitives in JavaScript, the third being Boolean.

JavaScript also has other types beyond primitives. The type diagram for JavaScript is as follows (as per Mozilla):

Ya really - Null and Undefined too.

Note, however, that this distinction between primitives and objects will be dismissed in JavaScript 2.0. You can read more about that here.

Type Coercion

Type coercion is a topic that is closely associated with loose typing. Since data types are managed internally, types are often converted internally as well. Understanding the rules of type coercion is extremely important. Consider the following expressions, and make sure you understand them:

7 + 7 + 7; // = 21
7 + 7 + "7"; // = 147
"7" + 7 + 7; // = 777

In the examples above, arithmetic is carried out as normal (left to right) until a String is encountered. From that point forward, all entities are converted to a String and then concatenated.

Type coercion also occurs when doing comparisons. You can, however, forbid type coercion by using the === operator. Consider these examples:

1 == true; // = true
1 === true; // = false

7 == "7"; // = true
7 === "7"; // = false;

There are methods to explicitly convert a variable's type as well, such as parseInt and parseFloat (both of which convert a String to a Number).

Double negation (!!) can also be used to cast a Number or String to a Boolean. Consider the following example:

true == !"0"; // = false
true == !!"0"; // = true
Conclusion

This obviously is not a definitive reference to loose typing in JavaScript (or type coercion for that matter). I do hope, however, that this will be a useful resource to those who are not familiar with these topics, and a good refresher for those who already are. I have tried to insure that the above is accurate, but if you notice anything incorrect, please let me know! And as always, thanks for reading!

Wednesday, March 12, 2008

I've Moved

Send to: blog.jeremymartin.name - handle with care

Well, under the recommendation of a few fellow bloggers, I have decided it's time to get my own domain. From now on my blog will be found at blog.jeremymartin.name.

For the time being, Blogger will still be serving my posts from the "blog" sub domain, which will allow me to serve any static content from my root level domain. For me, this beats all the static-page-in-Blogger hacks out there, and I will have a greater degree of control over the site. Thanks to everyone who reads!

Tuesday, March 11, 2008

My Java 7 Wishlist

Well, the JDK7 Project is underway, and despite the fact that I am being moved into the .NET world for some new projects, I wanted to leave some parting thoughts with the Java community. By no means do I consider myself the ultimate authority on the following topics, however, these are a few things that I propose would make Java a better, more friendly, more flexible language.

So here they are, in no particular order, my wish list for Java 7:

1. No More Primitives!

Seriously, primitives had their place and their time, but it's time to let them go. If you're using a boolean instead of Bool to save system resources, then you need to get a server that was made in the last decade. Performance is no longer a valid argument on this one (and that was about the only argument there ever was). OOP is OOP and primitives don't belong in OOP!

2. Tuples

Let me put it this way... how many times have you wanted to do something like this:

return (object1, object2);

See, now you want tuples too. Of course you always have the option of shoving them into some sort of a generic Collection, and then recasting them on the other side. But here's the problem: Collection's are meant to hold a collection of objects, they are NOT intended to be a form of community transit.

Another cool thing about tuples is they let you swap values without using a temporary variable, e.g. (x,y) = (y,x). That one's just for free...

3. Singleton Class Modifier

Do we need it? No. Would it be nice? Absolutely. Just let rules of a singleton Class be handled by the JVM, rather than leaving "singletoness" to be implemented by the designer. I suppose more importantly, singletons would be made thread safe by the JVM, a consideration that is often overlooked by singleton design patterns.

4. Scriptlets Inside JSP 2.0 Custom Tag Bodies

Ya, I know this is JSP, not strictly Java - but I'm stroking with a very broad brush here. I mean, why in the name of all that is good can't we do this?? Yes, scriptlets are inherently evil since the advent of JSTL, but what about those of us cursed with terabytes of legacy code that we do NOT want to convert to JSTL functions? Presumably custom tags still implement doBody() at some point or another, which already supports scriptlets. So again, why???

5. Heredoc String Support

This again is something that we don't need, but that I would definitely like to see. Java developers generally externalize any Strings large enough to justify heredoc format into a properties file - but this has its limitations; take for example a String that needs to contain a variable. I really don't care how it's implemented (e.g., StringBuilder, StringBuffer, plain Jane concatenation), but I want it.

6. Closures

While Java let's you get close to closures (using anonymous inner functions), your code ends up being really ugly and hardly readable. I think closures would be a big step towards making Java a more flexible language (without hurting your eyes at the same time).

7. Rationalize the Collections API

This would be big, it would be rough, and it would make a lot of developers angry. The idea of it actually scares me a little, but I'd contend that it has to happen sooner or later - and the sooner the better. Since my whole argument here is completely stolen, I'll just let you read it at the source.

And that's it. I wanted to make it a top 10 list, but I really didn't have enough to go on. I realize several of these topics are controversial - so let's hear it in the comments.

Friday, March 7, 2008

Total Recall

Reason #84 to make sure you're current with your vehicle's recalls:

Total Recall

Just uncovered this clip on my old computer. This was a tragic/shocking scene that my wife and I passed down in the L.A. area. This reminds me that I heard something about a recall concerning the speed control on our Explorer... better get on that...

Efficient Tag Cloud Algorithm

Hey all - since tag clouds are so popular these days, I thought I'd make a quick post about the algorithm I'm using to generate my tag cloud. I found a few sample algorithms already out there, but many of them seemed either inefficient, or didn't return the size that I was expecting.

Considering that the algorithm I'm using for my blog is running on the client side, I wanted to make sure that it was especially efficient. Here's what I ended up coming up with.

First, let's define the variables that are being used:

maxPercent
The font size is set as a percentage. This is the font-size percentage that the largest (most frequent) tag should be set to.
minPercent
This is the font-size percentage that the smallest (least frequent) tag should be set to.
max
This is the number of occurences for the most frequent tag.
min
This is the number of occurences for the least frequent tag.
count
This variable should be set inside of the link iterator. It refers to the number of occurences for the current tag.

Before I show some sample code for this, let's look at the actual algorithm for calculating the size:

var size = minPercent + ((max-(max-(count-min)))*(maxPercent-minPercent)/(max-min));

Since count is the only variable that changes during each iteration, we can extract the expression (maxPercent-minPercent)/(max-min) into its own constant and define it outside of the loop. This will save us two subtractions and a division operation for every loop. This now yields the following algorithm:

var multiplier = (maxPercent-minPercent)/(max-min);
var size = minPercent + ((max-(max-(count-min)))*multiplier);

The mathematical brilliance (sorry) behind this simple function isn't immediately obvious by looking at it, but the size returned will adhere to the following rules:

  1. The least occuring tag(s) will have a font-size of minPercent.
  2. The most occuring tag(s) will have a font-size of maxPercent.
  3. Tags with occurence counts in the middle will be scaled linearly.

Ok, let's look at this algorithm in action. The sample below uses a few jQuery methods (you all saw it coming), but this algorithm can certainly survive apart from any JS library. Notice that in the code below, I don't know min or max at the start. This means I have to loop through all of the tags twice, calculating these statistics the first time.

To give this code a real life context, I am generating a tag cloud out of the categories list that blogger generates. The markup that I am looping through is in the following format:

<div class="widget-content" id="categories">
 <ul>
  <li>
   <a dir="ltr" href="http://jmar777.blogspot.com/search/label/jQuery">jQuery</a>
   (<span dir="ltr">6</span>)
  </li>
  <li>
   <a dir="ltr" href="http://jmar777.blogspot.com/search/label/jTruncate">jTruncate</a>
   (<span dir="ltr">2</span>)
  </li>
  [etc...]
 </ul>
</div>

And here's the heavily commented javascript:

$().ready(function() {
 var catContainer = $('div#categories');
 // get an array of all the <li>'s
 var categories = catContainer.find('ul li');
 var cloudMarkup = '';
 // set maxPercent/minPercent preferences
 var maxPercent = 150, minPercent = 100;
 // note that max is initialized to a number that I know is lower than the max count
 // and that min is set to a number larger than the known min count
 var max = 1, min = 999, count = 0;
 // loop through each li and calculate statistics
 categories.each(function(i) {
  count = parseInt($(this).find('span').text());
  max = (count > max ? count : max);
  min = (min > count ? count : min);
 });
 var total, link, size;
 var multiplier = (maxPercent-minPercent)/(max-min);
 // loop through each li and generate the markup for the new tag cloud
 categories.each(function(i) {
  count = parseInt($(this).find('span').text());
  link = $(this).find('a');
  size = minPercent + ((max-(max-(count-min)))*multiplier) + '%';
  cloudMarkup += '<a class="cloud_link" style="font-size:' + size + '" href="' + link.attr('href') + '">' + link.text() + '</a> ';
 });
 // replace the html content of the parent container with the new tag cloud
 catContainer.html(cloudMarkup);
});

For you jQuery users out there - I am considering turning this into a plugin. I would like to hear from you what the expected markup should look like. For example, <a href="#" rel="[count]">tag</a> or <a href="#">tag ([count])</a>. Hopefully we can come up with something that doesn't completely violate the purpose of the rel tag, like that example! Thanks for your input!

Monday, March 3, 2008

jQuery - It's Here to Stay

So anyone who has been following this blog during its infancy knows that I have dedicated a lot of time to jQuery. Although my official title at work is Software Engineer, I have always had sway towards the client side technologies. Perhaps it's the instant gratification; no compile/build/deploy time, and everyone can appreciate it with no understanding of all the back end magic.

To cut out the story telling, I've found myself doing a lot more JavaScript-ing over the last few releases than my job description would have suggested. Never one to re-invent the wheel, I started researching some of the popular JS libraries out there. This post isn't intended as an analysis of why I eventually settled with jQuery, but suffice it to say that it became the obvious answer to many of our client-side needs.

After discovering the revolutionary ease of DOM selection, traversal, and manipulation in jQuery, I was then blown away by the level of productivity and logicality that chaining permits. If I want a div to fade in, flash 3 times, and then load some external content, I can group these related actions into one logical chain of events... all on the same line.

So apparently I became a believer. But I started wondering lately how popular jQuery has really become? Most of my immediate peers still drool and grovel over Prototype and Mootools (no offense to these other great libraries). My initial understanding was that jQuery must be the underdog struggeling to make a name. Well I did a little research and I was actually surprised by what I found. Check out these results from a Google Trends comparison:

Google Trends: jQuery vs. Scriptaculous vs. Mootools

These results are showing the number of Google queries for 'jquery' vs. 'scriptaculous' vs. 'mootools'. Although the chart doesn't reveal the total number of queries, it would appear that jQuery has received roughly three times the interest of scriptaculous or mootools. Obviously 'prototype' would have been a fairer comparison, but being a common dictionary term, the results would not truly indicate searches for the JS library.

This next chart by Alexa shows the number of page views (as gathered by Alexa) for jquery.com, prototype.js.org, and mootools.net.

Alexa: jquery.com vs. prototype.org vs. mootools.net

This comparison would indicate that mootools is doing better than the Google Trends chart indicated, however jQuery still has a commanding lead. This is great news for jQuery developers. If these numbers are any indication of adoption rates, then we can be sure that development will continue, and be confident in the already supportive community. Well... what more can I say? Congrats to John Resig and the whole jQuery team for delivering a great product, and of course to the whole jQuery community for making it a success!

Wednesday, February 27, 2008

Blogger Trick: Style Author Comments Differently with jQuery

No doubt you've encountered a blog at one time and noticed the custom styling applied to comments left by the author. It certainly adds a nice touch - and I wanted to be able to do the same here on Blogger. My first step towards finding a solution was to examine the comment markup generated by blogger. Unfortunately, however, it seems that Blogger doesn't indicate author comments in any way that can be accessed through a CSS rule. Well, I'm not that easily deterred, and eventually I came up with the following approach.

Before I explain how to implement this solution, let me briefly explain how it works. If you have ever looked inside your template's html, you have likely noticed some custom tags being used. In our case, we're concerned with the data tag. If this already sounds unfamiliar to you, I would advice you look at this page on using the data tag.

The particular piece of data that we want to access is the data.userUrl member. This member is only made available within the Profile widget, which unfortunately means that if you have disabled the profile on your blog, you're out of luck. This member is also not available if you have a team blog (sorry). For the rest of you bloggers (which is still the vast majority of you) this solution will work just great.

So now, with the preliminaries out of the way, we're going to tell the script to loop through all of the comments on the page. If the member link on the current comment matches the member link in the profile, then it must be an author comment. The script will then apply an additional class to the comment, allowing you to style it separately. All clear?

Step 1: Import the jQuery Library

In order for this script to work, you will have to import the jQuery library. Since jQuery let's you directly link to the source, this step is quite trivial. From your blog's dashboard, you will want to go to the layout tab, and then click "Edit HTML". Search for the <head> tag, and insert the following line directly below it:

<script src='http://code.jquery.com/jquery-latest.min.js' type='text/javascript'/>

Click "Save Template". Leave this page open because we'll be needing it in the following steps.

Step 2: Insert the Script

Now click the check box that says "Expand Widget Templates". Since the data.userUrl member is only available within the Profile widget, that is where we need to insert the script.

If are the only author of your blog, do this:

Search for the following tag:

<b:widget id='Profile1' locked='false' title='xxx' type='Profile'>.

Inside of this tag you will find the following line:

<b:else/> <!-- normal blog profile -->

Directly below this line, insert the following script:

<script type='text/javascript'>
$().ready(function() {
 $('dl#comments-block dt a').each(function(i) {
  if($(this).attr('href') == '<data:userUrl/>') {
   $(this).parent('dt').addClass('author-comment').next('dd.comment-body').addClass('author-comment').next('dd.comment-footer').addClass('author-comment');
  }
 });
});
</script>

If you have co-authors on your blog, do this:

Search for the following tag:

<b:widget id='Profile1' locked='false' title='xxx' type='Profile'>.

Inside this tag, you will find the following tag:

<b:if cond='data:team == "true"'>.

Immediately beneath this tag, insert the following code:

<script type="text/javascript">
 var author_urls = new Array();
</script>

Next, find the following line: <b:loop values='data:authors' var='i'>

Immediately below this line, insert the following code:

<script type="text/javascript">
 author_urls[author_urls.length] = '<data:i.userUrl/>';
</script>

Next, insert the following code right below the closing ul tag.

<script type='text/javascript'>
$().ready(function() {
 var urlsReg = new RegExp(author_urls.join("|"));
 $('dl#comments-block dt a').each(function(i) {
  if(urlsReg.test($(this).attr('href'))) {
   $(this).parent('dt').addClass('author-comment').next('dd.comment-body').addClass('author-comment').next('dd.comment-footer').addClass('author-comment');
  }
 });
});
</script>

That takes care of all the JavaScript parts. Now all that's left to do is to style it.

Step 3: Update your CSS

If you look at the markup that Blogger generates, you will notice that each comment is made up of a dt tag followed by two dd tags. At the time of writing this, I am using the following additional CSS:

dl#comments-block dt.author-comment {
  background-image: none;
  background-color: #EDE5BE;
  margin-bottom: 0px;
  padding: 6px 0 6px 10px;
  border: 1px solid #ccc;
  border-bottom: 1px solid #FFF7CF;
}

dl#comments-block dd.comment-body.author-comment {
  color: #593622;
  background-color: #EDE5BE;
  margin-top: 0px;
  margin-bottom: 0px;
  padding: 10px;
  border: 1px solid#ccc;
  border-top: 1px solid #CBC4AC;
}

dl#comments-block dd.comment-footer.author-comment {
  font-size: .8em;
  background-color: #CBC39C;
  padding: 3px;
  margin-top: 0px;
  float: right;
  border: 1px solid #ccc;
  border-top: none;
}

To add these styles, simply paste them right above the </style> tag.

You're Done!

That's it! Just hit "Save Template" and view your blog. To see the script in action, view my comment below this post.

Tuesday, February 26, 2008

jTruncate in Action

This is the demonstration page for the jTruncate plugin for jQuery. If you are looking for the jTruncate homepage, go here.

Plain Jane Example

jTruncate is called in the same way that most other jQuery plugins are called. The example below is using the following code, that accepts all the default options.

$().ready(function() {
 $('#example1').jTruncate();
});

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam fringilla, purus a ultrices blandit, odio ante scelerisque neque, vitae imperdiet odio velit ac nisl. Sed tortor metus, placerat condimentum, feugiat in, feugiat adipiscing, mi. Donec pulvinar sem vitae leo. Vestibulum eget lectus et ligula hendrerit pharetra. Sed porta justo ac nisl. Aliquam nisi erat, pellentesque sed, sagittis eu, fringilla sit amet, dolor. Nam ac mi. Pellentesque pede purus, mattis aliquet, semper nec, cursus a, orci. Duis bibendum nibh ac massa. Integer eu tortor. Aenean convallis quam at nunc. Nunc mollis tincidunt nisi. Suspendisse mauris odio, iaculis ut, feugiat vitae, ultrices in, tortor. Quisque at elit. In hac habitasse platea dictumst.
jTruncate Options

jTruncate allows you to customize nearly every aspect of the truncation operation. The following options are provided:

length: Defaults to 300
The number of characters to display before truncating.
minTrail: Defaults to 20
The minimum number of "extra" characters required to truncate. This option allows you to prevent truncation of a section of text that is only a few characters longer than the specified length.
moreText: Defaults to "more"
The text to use for the "more" link.
lessText: Defaults to "less"
The text to use for the "less" link.
ellipsisText: Defaults to "..."
The text to append to the truncated portion.
moreAni: Defaults to an empty string
The speed argument for the show() method (as specified here).
lessAni: Defaults to an empty string
The speed argument for the hide() method (as specified here).
Custom jTruncate Example

The following example demonstrates how to override the defaults described above.

$().ready(function() {
 $('#example2').jTruncate({
  length: 200,
  minTrail: 0,
  moreText: "[see all]",
  lessText: "[hide extra]",
  ellipsisText: " (truncated)",
  moreAni: "fast",
  lessAni: 2000
 });
});

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam fringilla, purus a ultrices blandit, odio ante scelerisque neque, vitae imperdiet odio velit ac nisl. Sed tortor metus, placerat condimentum, feugiat in, feugiat adipiscing, mi. Donec pulvinar sem vitae leo. Vestibulum eget lectus et ligula hendrerit pharetra. Sed porta justo ac nisl. Aliquam nisi erat, pellentesque sed, sagittis eu, fringilla sit amet, dolor. Nam ac mi. Pellentesque pede purus, mattis aliquet, semper nec, cursus a, orci. Duis bibendum nibh ac massa. Integer eu tortor. Aenean convallis quam at nunc. Nunc mollis tincidunt nisi. Suspendisse mauris odio, iaculis ut, feugiat vitae, ultrices in, tortor. Quisque at elit. In hac habitasse platea dictumst.
Special Considerations

Note that if you override the default animation options, you will notice a "new line" inserted at the point of truncation. This is because the hide/show methods require the animated element to be block level, and thus will begin on its own line.

Also note that jTruncate chooses the split location by starting at the length you specify (or the default) and then finds the next space. This is to prevent truncation in the middle of an html tag. This implies that the text needs to have spaces in it (duh), and that any tags within the truncated text cannot contain a space (i.e. <p id="myP"> = bad).

Thank you for visiting, and if you have any questions/suggestions at all, just let me know in the comments!

jTruncate - Text Truncation for jQuery

Welcome and thanks for visiting! This is the official home page for the jTruncate plugin for jQuery. In a nutshell, jTruncate provides simple yet customizable truncation for text entities in your web page.

Download

The latest version of jTruncate can be found at the following links:

Instructions/Examples

For usage instructions and working examples of the jTruncate plugin, look here.

Testers wanted!

To date I have tested jTruncate in FF2, IE6+, and Safari 3 (for windows). If you are running a browser other than what I have listed, please let me know how it performs! Due to the limited testing thus far, I am currently releasing jTruncate at version 0.8 - but it is a simple script and (until proven otherwise) I consider it to be stable.

Friday, February 8, 2008

Easy Multi Select Transfer with jQuery

I'm sure that at some point or another you've encountered a form widget like the one below, allowing options to be traded from one multi select to another.

add >>

I recently encountered a tutorial over at Quirks Mode on creating such a widget. While not a bad script, when all was said and done it was coming up on 40 lines of JS. I suppose that's not horrible, but we're talking about some simple functionality.

This struck me as a perfect example to demonstrate the simple and compact nature of jQuery coding. The widget operating above is running off of the following code:

$().ready(function() {
 $('#add').click(function() {
  return !$('#select1 option:selected').remove().appendTo('#select2');
 });
 $('#remove').click(function() {
  return !$('#select2 option:selected').remove().appendTo('#select1');
 });
});

That's it... 8 lines.

If you'd like to try it out, here's a working test page:

<html>
<head>
 <script src="js/jquery.js" type="text/javascript"></script>
 <script type="text/javascript">
  $().ready(function() {
   $('#add').click(function() {
    return !$('#select1 option:selected').remove().appendTo('#select2');
   });
   $('#remove').click(function() {
    return !$('#select2 option:selected').remove().appendTo('#select1');
   });
  });
 </script>
 
 <style type="text/css">
  a {
   display: block;
   border: 1px solid #aaa;
   text-decoration: none;
   background-color: #fafafa;
   color: #123456;
   margin: 2px;
   clear:both;
  }
  div {
   float:left;
   text-align: center;
   margin: 10px;
  }
  select {
   width: 100px;
   height: 80px;
  }
 </style>
 
</head>

<body>
 <div>
  <select multiple id="select1">
   <option value="1">Option 1</option>
   <option value="2">Option 2</option>
   <option value="3">Option 3</option>
   <option value="4">Option 4</option>
  </select>
  <a href="#" id="add">add &gt;&gt;</a>
 </div>
 <div>
  <select multiple id="select2"></select>
  <a href="#" id="remove">&lt;&lt; remove</a>
 </div>
</body>
</html>

As was mentioned in the comments below, the following (slightly modified) code can be used to automatically select all options in the second select box before submitting (thanks Charlie!).

$('form').submit(function() {
 $('#select2 option').each(function(i) {
  $(this).attr("selected", "selected");
 });
});

Just make sure you include that snippet inside the $().ready() method.

Update! (2/28/2008)

To prevent the page from scrolling to the top whenever a user clicks a button (in some browsers), I added return false; to the click event handlers.

(3/07/2008)

I included Charlie's suggestion from the comments into the main article. Thanks again Charlie! I also updated the the click event handlers to return false on the same line. Now it's only 8 lines!

(6/24/2008)

David Walsh has done an excellent port of this script for the Mootools library. You'll notice that the libraries allow for very similar syntax and nearly identical flow of logic. Check it out!

Wednesday, February 6, 2008

Java, Reflection, Hibernate Proxy Objects, and Confetti

After spending the last 3 days scratching my head and pushing Google to its theoretical limits, I have just experienced the ever-satisfying thrill of success. It was one of those moments where a little hole appears in the clouds and a beam of light illuminates my desk while gold and silver confetti float down from the overhead sprinklers. It really was that good; I nearly made an announcement over the intercom.

So here's the setup: we have a web application running on a Weblogic Portal server and we're using Hibernate and Spring. Due to application growth and an expanding data model, we decided it was time to turn lazy loading on (with respect to Hibernate). Meanwhile I'm working on some form processing logic that (for the sake of this discussion) needed to be a runtime annotation consumer.

The section of code was to determine whether a form had values for all of the "Recommended Fields". The recommended fields were designated via a RecommendedField annotation in the model class. All this method knows is that the particular model object will extend MySuperClass. So it's pretty straight forward. Here's a basic outline of what I had going:

public static boolean isComplete(MySuperClass object) {

 Method[] methods = object.getClass().getMethods();
 for(Method method : methods) {
  RecommendedField rField = method.getAnnotation(RecommendedField.class);
  if( null != rField) {
   // do some logic, then return true or false 
  }
 }
 
 return true;
}

Nothing seems glaringly wrong in the code above, but to my consternation, method.getAnnotation() always returned null. Around this time I came to understand one of the side effects of Hibernate lazy loading. In order to allow lazy access to any relational objects, Hibernate returns a "proxy" object that essentially wraps and mimics the object that you wanted. This way when you call a getter, instead of throwing a NullPointerException, Hibernate can retrieve the result from the database.

Great... so what now? While the proxy object will suffice whenever you need to access a public property or method, it quickly becomes apparent that introspection and reflection present a problem. Since the proxy object is not truly an instance of the class that it is wrapping, metadata (such as annotations) are not there.

In truth, this realization was the key to solving the problem. Understanding that the annotations simply didn't exist on the object that I was inspecting prompted me to explore how to retrieve the non-proxy version of the object. Here is the solution that I ultimately came up with:

public static boolean isComplete(MySuperClass object) {
 /*
  *  The type casting below is necessary in order to read the annotations on the object's methods.
  *  The "MySuperClass" object that is passed into this method is really a Hibernate proxy object 
  *  that wraps the MySuperClass object (due to Hibernate's lazy loading).
  */
 if (object instanceof HibernateProxy) {
  object = (MySuperClass)((HibernateProxy)object).getHibernateLazyInitializer().getImplementation();
 }
  
 Method[] methods = object.getClass().getMethods();
 for(Method method : methods) {
  RecommendedField rField = method.getAnnotation(RecommendedField.class);
  if( null != rField) {
   // do some logic, then return true or false 
  }
 }
 
 return true;
}

*Cue confetti*

You'll notice that the commented addition is rather peculiar. It essentially takes the proxy object that was passed in and casts it as a HibernateProxy object. Calling getImplementation() returns a generic object, which I can then recast as a MySuperClass object (which is what it claimed to be in the first place). Since the object I am working with is now a real and true instance of MySuperClass, I can inspect the methods and their annotations without any problems.

There is a word of warning to throw in about this solution: since I am replacing the proxy object with the real object, my assumption is that it is now detached from the Hibernate session. Attempts at lazy loading on the object would most likely return null or throw a LazyLoadException (I have not tested to verify). In my case I don't need to access any more data, so it's not a problem. If your circumstances are different, you can simply create a new instantiation out of the casted object, or attempt to reattach the object to the Hibernate session when you're done.

Sunday, February 3, 2008

Building Your First jQuery Plugin

So you were out on your quest to find the answer to life, the universe, and everything, when blam, you found jQuery. Yes, I know, you were expecting 42, but too all of our surprise, it was jQuery. So what's next? Build your own plugin!

While some are intimidated by the thought of creating their own plugin, the truth is that jQuery is built with an infinitely friendly plugin architecture. If you've gotten comfortable with the basics of jQuery coding, then you're certainly ready to develop your own plugin. This tutorial will take you step by step through creating your very own truncation plugin. Say, for example, you have a "tip of the day" widget on your home page. This plugin will let you truncate it to a specified length, with a link to expand it to view it's full content. Here's a working example:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam fringilla, purus a ultrices blandit, odio ante scelerisque neque, vitae imperdiet odio velit ac nisl. Sed tortor metus, placerat condimentum, feugiat in, feugiat adipiscing, mi. Donec pulvinar sem vitae leo. Vestibulum eget lectus et ligula hendrerit pharetra. Sed porta justo ac nisl. Aliquam nisi erat, pellentesque sed, sagittis eu, fringilla sit amet, dolor. Nam ac mi. Pellentesque pede purus, mattis aliquet, semper nec, cursus a, orci. Duis bibendum nibh ac massa. Integer eu tortor. Aenean convallis quam at nunc. Nunc mollis tincidunt nisi. Suspendisse mauris odio, iaculis ut, feugiat vitae, ultrices in, tortor. Quisque at elit. In hac habitasse platea dictumst.

Note that if JavaScript is disabled (or not supported) the content will simply display in it's entirety.

You ready? Let's dig in...

Step 1

The first step is to extend the actual jQuery object with the function that we wish to add. In our case, we wish to add "truncation" functionality. So here's where to start: create a jquery.truncate.js file and save it with the following code:

$.fn.truncate = function(options) {

   return this.each(function() {

   });
};

Now you may have heard that plugin developers should not user the $ alias, as this can result in conflicts with other libraries. This is only partially true. The following snippet is the same as the one above, except that we pass jQuery into the function, allowing us to use an alias we want. We'll stick with $.

(function($){
 $.fn.truncate = function() {

    return this.each(function() {

    });
 };
})(jQuery);
Step 2

Before we go any further, let's create a simple test page that we can use to test our plugin. Create a page and call it whatever_you_want.html. Insert the following code. As you can see I placed both the jQuery library and the plugin inside a folder named js. Note that we are already invoking our plugin in this snippet, although we have not yet coded any behavior.

<html>
<head>
 <title>Truncation Plugin Test</title>
 <script src="js/jquery.js" type="text/javascript"></script>
 <script src="js/jquery.truncate.js" type="text/javascript"></script>
 
 <script type="text/javascript">
  $().ready(function() {
   $('.tip').truncate();
  });
 </script>
</head>
<body>
 <div class="tip" style="width:200px;background-color:#ccc;padding:10px;">
  Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam fringilla, purus a ultrices blandit,
  odio ante scelerisque neque, vitae imperdiet odio velit ac nisl. Sed tortor metus, placerat condimentum,
  feugiat in, feugiat adipiscing, mi. Donec pulvinar sem vitae leo. Vestibulum eget lectus et ligula hendrerit
  pharetra. Sed porta justo ac nisl. Aliquam nisi erat, pellentesque sed, sagittis eu, fringilla sit amet,
  dolor. Nam ac mi. Pellentesque pede purus, mattis aliquet, semper nec, cursus a, orci. Duis bibendum nibh
  ac massa. Integer eu tortor. Aenean convallis quam at nunc. Nunc mollis tincidunt nisi. Suspendisse mauris
  odio, iaculis ut, feugiat vitae, ultrices in, tortor. Quisque at elit. In hac habitasse platea dictumst.
 </div>
</body>
</html>
Step 3

The next thing we want to do is provide a mechanism for the user to customize the plugin. While we want to make the plugin as flexible as possible, we should also provide defaults so that the user isn't forced into providing a long list of parameters. We can easily do this using jQuery's extend method. Update your plugin to match the following:

(function($){
 $.fn.truncate = function(options) {

  var defaults = {
   length: 300,
   minTrail: 20,
   moreText: "more",
   lessText: "less",
   ellipsisText: "..."
  };
  var options = $.extend(defaults, options);
    
  return this.each(function() {

  });
 };
})(jQuery);

For now we won't override any of the defaults in our test page, but we'll demonstrate this later.

Step 4

So that takes care of all the preliminary considerations. Let's get to coding the plugin's functionality. As you've already seen, the plugin is returning this.each(...). This line will execute the contained anonymous function on each item in the jQuery array. So, if for example we called $('p').truncate(), the code we're about to write would execute on every p tag.

Since I'm assuming a comfortable understanding of jQuery, I won't explain in detail how the function's code actually works. If anything in the code is not obvious, you should refer to the documentation or ask a question in the comments. To complete your plugin, update it to match the following:

(function($){
 $.fn.truncate = function(options) {
    
  var defaults = {
   length: 300,
   minTrail: 20,
   moreText: "more",
   lessText: "less",
   ellipsisText: "..."
  };
  
  var options = $.extend(defaults, options);
    
  return this.each(function() {
   obj = $(this);
   var body = obj.html();
   
   if(body.length > options.length + options.minTrail) {
    var splitLocation = body.indexOf(' ', options.length);
    if(splitLocation != -1) {
     // truncate tip
     var splitLocation = body.indexOf(' ', options.length);
     var str1 = body.substring(0, splitLocation);
     var str2 = body.substring(splitLocation, body.length - 1);
     obj.html(str1 + '<span class="truncate_ellipsis">' + options.ellipsisText + 
      '</span>' + '<span  class="truncate_more">' + str2 + '</span>');
     obj.find('.truncate_more').css("display", "none");
     
     // insert more link
     obj.append(
      '<div class="clearboth">' +
       '<a href="#" class="truncate_more_link">' +  options.moreText + '</a>' + 
      '</div>'
     );

     // set onclick event for more/less link
     var moreLink = $('.truncate_more_link', obj);
     var moreContent = $('.truncate_more', obj);
     var ellipsis = $('.truncate_ellipsis', obj);
     moreLink.click(function() {
      if(moreLink.text() == options.moreText) {
       moreContent.show('normal');
       moreLink.text(options.lessText);
       ellipsis.css("display", "none");
      } else {
       moreContent.hide('normal');
       moreLink.text(options.moreText);
       ellipsis.css("display", "inline");
      }
      return false;
       });
    }
   } // end if
   
  });
 };
})(jQuery);

You'll notice that whenever I needed to select an element within the plugin, I always used obj as my context (e.g., moreLink = $('.truncate_more_link', obj)). This is necessary to constrain any selections to the current truncated element. Without setting the context like this, you will get unpredictable results.

So that's it - your first jQuery plugin! We're not quite finished though, since I promised we'd demonstrate overriding the default options. In the following example, every option has been over ridden, although it is perfectly valid to override fewer. Just replace the script in your test page with this:

$().ready(function() {
 $('.tip').truncate( {
  length: 120,
  minTrail: 10,
  moreText: 'show more',
  lessText: 'show less',
  ellipsisText: " [there's more...]"
 });
});

This code will give you something like this:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam fringilla, purus a ultrices blandit, odio ante scelerisque neque, vitae imperdiet odio velit ac nisl. Sed tortor metus, placerat condimentum, feugiat in, feugiat adipiscing, mi. Donec pulvinar sem vitae leo. Vestibulum eget lectus et ligula hendrerit pharetra. Sed porta justo ac nisl. Aliquam nisi erat, pellentesque sed, sagittis eu, fringilla sit amet, dolor. Nam ac mi. Pellentesque pede purus, mattis aliquet, semper nec, cursus a, orci. Duis bibendum nibh ac massa. Integer eu tortor. Aenean convallis quam at nunc. Nunc mollis tincidunt nisi. Suspendisse mauris odio, iaculis ut, feugiat vitae, ultrices in, tortor. Quisque at elit. In hac habitasse platea dictumst.

Well... I hope you found this helpful. If you have any questions beyond what I've explained, please just ask in the comments. Thanks for reading!

Update! (2/26/2008)

The plugin that we just developed above has now been added to the jQuery plugin repository under the name of jTruncate. The home page is located here on my blog. It is now an evolving beast, so check there for any updates.

Thursday, January 31, 2008

'08 Candidates and Healthcare

As the nation looks forward to the upcoming Super Tuesday primaries, many voters are still trying to lock in on their candidate of choice. Between the political mud slinging and pundit biases, this decision is never an easy one. Campaign issues this year have been numerous and polarizing - more so than usual. There is one issue in particular that strikes me as deserving more than the relatively scanty media attention that it has received.

Healthcare in the '08 election has served as an overused campaign buzzword, but the specifics seem to get overlooked. By now most everyone has associated some sort of a "socialized, universal coverage" label with the Democratic hopefuls, and a "free market, tax refunds" solution with the Republicans. Though not entirely inaccurate, these blanket statements certainly do not demonstrate a necessary understanding of the intricate differences among this year's campaigners.

While I certainly have my political leanings, and they will doubtless become apparent if I keep this blog up (yeah for my first post!), this particular entry is intended as a completely neutral "middle man" source for you. I say "middle man" because the ultimate purpose of this post is to present you with some helpful videos found over at icyou. I suppose some of you might cry blogspam at this, but I feel I've written long enough of a prelude - so lay off :p

To watch a video, simply click on the candidate's name. Although there was also a video for Edwards, I removed it from this list due to him dropping out of the race.

Obama Romney McCain Huckabee Clinton

I have tried to present these videos in a convenient manner, but due to compatibility issues the above links might not work for some. So just in case, here are the direct links: Obama
Romney
McCain
Huckabee
Clinton