Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Wednesday

GitHub, Taming document.write and node.js fun

I have a few projects on GitHub now.

The serious project is writeCapture.js. It exists to solve a corner case of the "load some HTML and inject it into the document" pattern. I love this pattern because it's generally the simplest way to combine Ajax with progressive enhancement. The idea is that you load a HTML fragment and just stick it into the document, or replace the old fragment with the new fragment. It degrades easily, and keeps things simple. The only problem is when the HTML you're loading is outside of your control, or can't be changed for some reason. Maybe it's a service provided by a 3rd party. If the HTML contains script tags, and the script tags contain calls to document.write, you're going to have 1 of 2 bad outcomes:
  1. If you just use innerHTML, the scripts probably wont run (at least, not in every browser), so whatever content document.write provides will be missing. That's probably bad.
  2. If you use jQuery.html() or .replaceWith() or any jQuery manipulation method, the scripts will run, and all the content already in the document gets wiped out. Oops.
So this is the part where you realize that you need writeCapture.js. It's open source, well tested, and covers every possible convoluted way that document.write can be slipped into a script: inline, local script file, cross domain and any combination of the 3 (even the script that writes a script tag that includes a script that uses document.write case. Seriously.) You're welcome.

Lastly, I've been having fun with node.js. node can do a lot of things, but using it as a web server/application is the one that appeals to me most, so I wrote a simple web server that streams whatever files are in the current directory. Of course, you can make it do anything you want in response to a HTTP request (or use raw sockets, or whatever) and I'm sure there are a dozen (G)rails like frameworks being written for it as we speak. Enjoy.

Thursday

JS Tips & Tricks

http://javascript.crockford.com, Secrets of the JavaScript Ninja and JavaScript: The Good Parts will cover almost everything you need to know about JavaScript. Still, there are a few tricks that I use almost every day that I feel are often underrated:
  • && and || aren't your father's boolean operators. Thanks to JavaScript's notion of truth (anything but false, null, 0, undefined and the empty string), they don't have to return boolean value, and will not unless you coerce it into one with !!. That means you can use them inline as part of assignments and in parameter lists. e.g,
    function(someParam) {
    // provide a default value
    someParam = someParam || {};
    // ...
    }

    // guard against null objects
    var count = foo && foo.count || 0; // if foo is null, count == 0, else foo.count
  • function scope:
    (function($){
    $('#foo').doSomething();
    // ...
    })(jQuery);
    The key here is that you're taking a global/wider scoped variable and making it a local variable, which allows you to rename/replace the original variable with little to no impact to your code. For example, suppose you need to use 2 versions of jQuery in your page. If you have the good sense to wrap all of your scripts in a function, you can include jQuery version A, then include your scripts that need version A, then include jQuery version B and your other scripts. Or if you wrote all of your scripts using $ as a reference to jQuery and then wanted to use Prototype in the same page.

    The other nice thing about wrapping your scripts is that any vars and function your define wont bleed into the window scope unless you specifically assign them to window. e.g., window.GLOBAL_FOO = 123;

Sorry for the short post. I have some more code heavy stuff I think I'm working on for next time, I promise.

Wednesday

Quit being lazy. lern2javascript noob

[Note: This is a blog post from a year ago, but I'm reviving it because I'm seeing developers and companies lose work because they don't have JavaScript experience. If you work on web applications, you need to learn JavaScript. In addition to this post, which targets Java developers, I've added links to good getting started resources at the end.]

Prologue: Why you need to learn JavaScript

For the foreseeable future (probably the next 5-10 years), the majority of software development will be done on web applications. Many of these will be ports of existing desktop applications or designed to replace such applications. Developing desktop-like applications on the web is going to require that Ajax thing you've been hearing about, something called DHTML, DOM, etc. That means you'll be using JavaScript.

We Java developers have been conditioned to flee at the first mention of JavaScript which has meant that it has long been the job of the 'creatives' to do the JavaScript work. That's not going to cut it anymore. While the work UX experts do is crucial to developing any application, they have different training, priorities and experiences. RIAs need solid technical developers who understand best practices, patterns, unit testing, etc. and can apply them to JavaScript.

One way Java developers try to avoid having to deal with JavaScript is through frameworks like JSF or GWT. There are certainly advantages to using a framework, but they are no substitute for being comfortable with JavaScript. Developing RIAs through a framework without knowing JavaScript is like using Hibernate without a solid understanding of SQL and relational databases. You may get by, but it wont be easy and it wont be pretty.

Hopefully you're now convinced that JavaScript is in your future. I want you to know that you don't have to be dragged into it kicking and screaming. It will be fun. You know those closure things that they're talking about putting in Java 7? JavaScript has always had them. Ever get tired of writing the same Java code over and over? JavaScript code is far shorter and less repetitive.

Differences: The Good, The Bad, and The Ugly

I'm going to focus on the immediately important differences for now. We'll pick up the more subtle ones as we go.

  • JavaScript, like Java, has a C like syntax so you should feel pretty much at home. It has fewer keywords than Java, but adds a few new ones. The most important one is function, which we'll talk about more in the next chapter, but there's also var(declares a variable), with (to generally be avoided), and in (multiple uses).

  • JavaScript is loosely (weak) typed. For a UI, that's a good thing, because most of the data you're working with is string data, so you don't have to declare String everywhere and if you need a string to occasionally be a number, it happens automatically. Every object has a boolean value of true except 0,the empty string and false. An undefined or null variable also evaluates to false, so you can check to see if an object has the method/property that you want like so:
    if(!foo.bar) {
    throw "foo must have bar";
    // you can throw anything to raise an error
    }
    Of course, you can do whatever you like if the object you were passed doesn't have a particular method.

  • There are only Numbers in JavaScript. There is no distinction between int,float, double and long. Math.round, Math.floor and Math.ceil are there if you need them. The maximum value is 1.7976931348623157e+308 so don't worry too much about overflowing. You shouldn't be doing any heavy computation on the client anyways. If you try to do arithmetic with something that isn't a number, the result will be NaN (not a number). NaN and anything is NaN. That includes undefined variables:
    var foo = 1;
    foo + bar; // == NaN, since bar is undefined
  • There is no char type. You can use either single or double quotes to delimit a string. 'f' is always the string "f". charCodeAt(index) on strings will give you the character code as a number.

  • In addition to functions, objects and arrays are first class citizens (technically functions and arrays are also objects). You can define array literals using the [] syntax: var myArray = [1,2,3];. For objects you use {} and provide a list of name:value pairs: var myObj = { foo: "bar", baz: [1,2,3] }. Both array and object literals can span multiple lines. It's generally good form to break lines after a comma (if you must break lines):
    var foo = {
    bar: "baz", qux: 123,
    quxx: { a: 1, b: 2, c: 3}
    };
  • Perhaps the most important JavaScript data type is the function. We wont get into it now, but you need to know that you can treat functions like any other variable. e.g.,
    var foo = function(a,b) {
    return a + b;
    };

    foo(1,2); // == 3
  • When a function is called as a property of an object, it gets access to this. e.g.,
    var foo = new Object();
    foo.bar = function(a) {
    return a + this.b;
    };
    foo.b = 2;
    foo.bar(1); // == 3
    foo.bar(2); // == 4

  • Note that while you can get put a reference to foo's bar function in a variable, it will no longer have access to foo via this.
    var bar = foo.bar;
    bar(2); // == NaN (not a number)
    Since this.b is undefined, 2 + undefined is NaN. You might be wondering why this.bar doesn't result in an error. Well, it's because this is always defined. Since JavaScript executes in the context of the browser window, the default this is the window. This is where all global variables live. Incidentally, you can reference the window explicitly with the window object.

  • There is a difference in scoping in JavaScript as well. You're used to having block local variables. Well, in JavaScript variables are either global or function local. Blocks share their enclosing scope, so
    var foo;
    if(true) {
    foo = 1;
    }
    is the same as
    if(true) {
    var foo = 1;
    }
    foo will still be visible after the else block. If you fail to define a var inside a function, a global variable is created (or if it exists it is overwritten). e.g.,

    function() {
    foo = 1; // sets window.foo = 1
    }
    So, think carefully about scope when you declare and use variables.

  • JavaScript is interpreted, which means that you don't even know 100% if a line of your script is valid until it actually runs. That makes unit testing crucial. Fortunately tools like JUnit, Javadoc, etc. all have JavaScript equivalents that will seem very familiar. There are also a host of development tools including Eclipse plugins, Aptana, IntelliJ support, etc. to help you along.

  • Lastly, you should know that JavaScript inheritance is prototypal. It is fully possible to achieve class based inheritance, which we will do with the help of a library called Prototype, but the prototypal nature of JavaScript gives us some interesting options which we will explore later.

Your Environment

We're Java developers, so we know the power of a good IDE. Eclipse, NetBeans and IntelliJ all have decent JavaScript support. There are a variety of plug-ins for Eclipse (I use JSEclipse), but I'm going to tell you right now that none of them will give you the code completion that you're used to. It's simply not possible with a dynamic, weakly typed language. You'll have to learn APIs the old fashioned way, by reading the docs and using them.

Fortunately, JavaScript gives you an amazing debugging and exploratory tool that you have never had and likely will never have with Java. Its name is Firebug. Go ahead and install it. Done? You need to restart Firefox. OK. Good. Now see in the bottom right corner? Click it. This is Firebug. It does a lot of things, but for now we're just going to mess around with the 'command line'. Do the following:
  1. Click the in the bottom right corner of Firebug.
  2. Paste this into the command line and press Ctrl+Enter or click 'Run':
    $('demoSteps').childElements().each(function(item,i) {
    item.insert("("+i+")");
    });
OK, it's not the most impressive example, but you did just execute code without having to reload the page or anything. Here we're making use of a library called Prototype. Bookmark the API immediately. What the above code does is call a function named '$' (yes, that's a valid variable name in JavaScript) with the argument 'demoSteps'. When $ is given a string, it looks for the element in the HTML with id="demoSteps". We get the child elements and iterate over them, calling the anonymous function we defined there on each element, along with it's index. We then append the index in parentheses to the body of each element.

The equivalent JavaScript without Prototype is a lot longer. You could start learning JavaScript without any libraries, but then you'd quickly get caught up in fixing bugs and writing the same code over an over. Fixing bugs doesn't give you a good appreciation for a language, nor does clunky repetitive code. In any serious web project you will use Prototype or a similar library, so it doesn't hurt to know it. After you're comfortable, we will delve deeper into the JavaScript language and you'll learn what Prototype hides from you.

Before we go, drag this onto your bookmarks toolbar: Insert Prototype. Now you can go to any web page, click that bookmarklet, pop open the console and start using Prototype to play. For homework, explore the Prototype API, especially the utility functions and the Enumerable methods. Try to write as many snippets using the API as you can.

Resources

Friday

One liners for readability

(For clarity, when I say one liner, I mean single statement. For various reasons, including readability, it may be desirable to split statements across multiple lines)

Which is easier to read? Is it this multi-statement snippet:
def params = request.params
def config = whatever.getMyConfig()
def request = MyLongTypeNameRequestTransformer.toMyRequest(params, config)
def result = myLongNamedServiceThatDoesSomethingCool.execute(request)
or this single statement:
def result = myLongNamedServiceThatDoesSomethingCool.execute(
MyLongTypeNameRequestTransformer.toMyRequest(
request.params, whatever.getMyConfig ) )
// line breaks added to protect the page-width. 80 columns
Now your answer to that question probably depends on how you interpreted 'easier to read'. Most of you probably thought that I meant "Which format makes it easier to understand what this snippet does?" Typically people are going to say that the first one is more clear in that respect. However, I want to consider a different question, "Which format makes it easier to understand/follow/debug/grok/refactor the overall codebase?"

I would argue that the second form is better in that respect, and that overall manageability of a codebase is generally more important than a small readability improvement for a section of code. I see one liners as an implied abstraction. It hints to the reader that, despite the complexity involved, we are really only interested in one result (either a return value or a side effect), so they can mentally collapse all that code into "get X" or "do Y". It says, "Skim over me, the details are not important."

There are two alternatives to one liners. The first is to use a bunch of local variables. While this can certainly make an algorithm more readable, each one adds one more thing that I have to keep track of when I'm reading your code. I have to remember that config came from whatever.getMyConfig(), and I have to consider that it may be used later in the method. If config is inlined, I don't even have to mentally register its existence unless I'm trying to parse the one liner.

The second alternative is to encapsulate the snippet as a function. This gets rid of the mental scope pollution from stray variables, but it introduces two new problems. Firstly, if I want to know what the function does, I have to go to another place in the file (or another file), which breaks the continuity. Often times one liners also need several of the variables in the current scope, so you end up with a lot of parameters, which adds even more clutter. Secondly, you end up poluting the scope of the class or script with yet another function that is only used in one place. You've just moved the clutter up a level.

Now, there are certainly times and places where you don't want to inline everything all willy nilly. If an expression appear multiple times in a function (e.g., whatever.getConfig()), don't repeat yourself, use a local variable. If you can extract a function that can be used in more than one place, go right ahead. If you have code that is several indentation levels deep, first consider a redesign and/or refactoring that simplifies, but if that doesn't work, extract a function to make it more readable. However, declaring variables and functions should be things that you do out of a clear need, not just because you think you'll need it, or because your CS professor always told you to (CS professors are concerned with algorithms and minutia, not codebase managability). Remember, premature optimization is the devil.

Most modern languages offer syntax that can assist in creating readable one-liners. If your language has map/has and/or list literals, you should avoid building those constructs procedurally. e.g., in JavaScript:
var array = new Array();
array[0] = 'foo';
array.push('bar');
myMethod(array);
is lame. Write that as
myMethod(['foo','bar']);
Groovy's map literal:
myMethod([foo:'bar',baz:'quxx']);
Even Java can be slightly improved thanks to anonymous inner classes and initializer blocks:
myMethod(new HashMap() {
{
put("foo","bar");
put("baz","qux");
}
});
Hopefully you have the idea by now.

Wednesday

Java Fun Continued - Groovy FTW

Here's the equivalent Groovy for my previous Java abomination that prints the Java wrapper methods for me:

new File("src/main/java/Foo.java").text.
replaceAll(/(?sm)\s*public\s+(\S+)\s+(\S+)\((.*?)\)\s*\{/) {
s,ret,name,params ->
print """
public ${ret} ${name}(${params}) {
"""
if("void" != ret) {
print "return "
}
print "foo.${name}("
// -1 hack avoids index out of bounds when params is ''
print params.trim().split(/\s*,\s*/).collect {
it.split(/\s+/)[-1]
}.join(',')
print """);
}
"""
}

I could change the prints to concatenation and reformat the whole thing as a single line, so it only counts as one statement. Technically I cheated a little because this version doesn't look up the methods by reflection, but it doesn't make a difference in the result, and wouldn't significantly shorten the Java code. Definitely more readable than the Java. The JavaScript is a little messier since you don't have multi-line string literals, GStrings, and closures are function(it){ return it.foo; } instead of { it.foo }.

Monday

The IE script load event

This is just a short rant. I promise I'll post more about Grails latter.

I really hate IE. Take this code to create a script tag and fire a callback once it's loaded:

var script = document.createElement("script");
script.setAttribute("type","text/javascript");
script.setAttribute("src", fileName);
Event.observe( script, "load", function() {...});

Works great in Firefox. But in IE6? Never fires. You have to do this instead:

Event.observe( script, "readystatechange", function() {
if(script.readyState == "complete") {
...do stuff...
}
} );

It's not that there is extra functionality. It's that a decision was made to provide a complicated interface that can handle like two extra edge cases, but the much simpler, obvious and consistent 'onload' handler gets left out.

Friday

Custom DWR Converters

DWR is great. If you're full bore into Ajax development, it eliminates the need for a awkward controller like JSF or Spring MVC. You can write static DHTML that talks directly to your service layer, which keeps the UI code clear and simple. Secure your services with something like Acegi, and you're almost there.

I say almost, because the way DWR marshals your beans is either all or nothing. You can tell DWR, convert only these classes, and only these properties and that's it. What if you have different user roles that have different read permissions? e.g., detailed user info should be accessible to the admin and no one else. What if you want summary information when an object is nested inside another one? e.g., my Label BO has a name, description and a couple of flags associated with it. When I retrieve a labeled thing, say a message, I really only care about the label name so I can render a list of labels on the message. But when I retrieve a Label for editing, I need all the information about the label. Let's see if we can fix this.

Because DWR is open source, I can browse around and find the source for BeanConverter. It has a lot of hooks (including isAllowedByIncludeExcludeRules, which would be helpful for role based filtering), but what we really need here is a hook to control what converter is used. Because we have the source code, why don't we add one? I'll just create a subclass of BeanConverter and override convertOutbound like so:

public OutboundVariable convertOutbound(Object data, OutboundContext outctx)
throws MarshallException {
Map ovs = new TreeMap();

ObjectOutboundVariable ov = new ObjectOutboundVariable(outctx);
outctx.put(data, ov);

try {
for (Entry entry : (Set>) getPropertyMapFromObject(
data, true, false).entrySet()) {
ovs.put((String) entry.getKey(), getPropertyValue(
(Property) entry.getValue(), data, outctx));
}
} catch (MarshallException ex) {
throw ex;
} catch (Exception ex) {
throw new MarshallException(data.getClass(), ex);
}

ov.init(ovs, getJavascript());

return ov;
}

The code is pretty much the same as in the superclass, but with 1 key difference. My version calls getPropertyValue. In the template class, I keep the default behavior, loading the converter from the converter manager, but we'll create a subclass in a moment that takes a different approach.

First, let's look at what dwr.xml offers us in terms of configuration. It looks like you can set properties on converter instances using param elements. I prefer to use a concise format for configuration whenever possible, so our format will be something like "propertyName:includeExcludeProperty1,includeExcludeProperty2 otherProp:more,of,the,same". Supposing this was an include, then when we create the converter for the otherProp property, it will include the more,of,the and same properties and no others. Got it?

We need to provide parsing for our custom format in the converter:

public class SubBeanConverter extends TemplateBeanConverter {

protected Map subInclude = new HashMap();
protected Map subExclude = new HashMap();

public void setSubIncludes(String defs) {
this.subInclude = parseIncludeExclude(defs, true);
}

public void setSubExcludes(String defs) {
this.subExclude = parseIncludeExclude(defs, false);
}

private Map parseIncludeExclude(String defs,
boolean include) {
Map map = new HashMap();
for (String def : defs.split("\\s")) {
String[] split = def.split(":", 2);
BeanConverter bc = new BeanConverter();
bc.setConverterManager(getConverterManager());
if (include) {
bc.setInclude(split[1]);
} else {
bc.setExclude(split[1]);
}
map.put(split[0].trim(), bc);
}
return map;
}
...

TemplateBeanConverter is our original subclass of BeanConverter. Since we're using the same format for includes and excludes, the same method is used to parse them both. For each property we list, we create a BeanConverter instance that we will use in place of the usual converter.

The last step is to override getPropertyValue and use our special BeanConverter instances:

protected OutboundVariable getPropertyValue(Property property, Object data,
OutboundContext outctx) throws MarshallException {
Object value = property.getValue(data);
if (value != null) {
BeanConverter exConverter = subExclude.get(property.getName());
if (exConverter != null) {
return exConverter.convertOutbound(value, outctx);
}
BeanConverter inConverter = subInclude.get(property.getName());
if (inConverter != null) {
return inConverter.convertOutbound(value, outctx);
}
}
return super.getPropertyValue(property, data, outctx);
}

Easy right?

Next time I'll talk about my experience using Grails with DWR.

UPDATE: I mentioned role based filtering above, but I will leave that as an exercise to the reader. One hint: if you're using Acegi to control access to pages,
org.acegisecurity.context.SecurityContextHolder.getContext()
.getAuthentication().getAuthorities()
will get you the list of granted authorities (AKA roles, e.g. ROLE_ANONYMOUS) for the current user.

Thursday

More than you wanted to know about JavaScript object creation

I began this journey because I needed to create a new instance of a JavaScript class with a variable number of arguments. Not knowing the number of arguments, I couldn't just write new MyClass(arg[0],arg[1].. etc.), so I had to figure out how to replicate the behaviour of new in some other way.

You may have heard that JavaScript inheritance is prototypal. If you don't know what that means, thin of it as one object inheriting from another by making a copy of the original object. Everything in JavaScript is an object, including functions. You may think that JavaScript has classes. It doesn't. It really just has functions.

JavaScript is prototypal, but it wanted to appeal to programmers that were used to "classical" inheritance, so it included the 'new' keyword that we all love so much. That means you can do things like:

function MyClass(arg1,arg2) {
this.foo = arg1;
this.bar = arg2;
this.baz = 3;
}
var mine = new MyClass('foo','bar');
// mine.foo == 'foo'
So what's going on? MyClass is called, but there is this 'this' object that isn't declared anywhere. Where did it come from? new created it for us and put it into the scope of the MyClass function. If a function called with 'new' doesn't have a return statement, it returns 'this' by default. You could try to call MyClass by itself, but you would end up creating 3 global variables because this defaults to window. So how do we redefine this? There are two methods on all functions (remember, functions are objects, just like everything else) that let you control the value of this: call and apply.
var foo = { qux: '123' };
MyClass.call(foo,'foo','bar');
// foo.foo == 'foo' && foo.qux == '123'
// if you don't know the exact number of arguments you can use apply
var args = ['foo','bar'];
// apply takes an array for the arguments
MyClass.apply(foo,args);
You might now be thinking that MyClass.call({},'foo','bar') is the same as new MyClass('foo','bar'). Well, new does a bit more than that. Remember the prototype? Calling new more or less creates a copy of the class's prototype, which is then used as this when calling the function. e.g.

MyClass.prototype.myFunc = function(a,b) { return a+b; };
var mine = new MyClass(...);
// mine.myFunc == function(a,b) { return a+b; }


One brief digression from our quest: John Resig blogged about a way to create classes that are instantiated correctly even if you forget new. An interesting read, but not quite what we need since we may need to instantiate classes not under our control.

So if you create a new object, copy all the properties of MyClass.prototype, and then call MyClass.apply(...), is that the same as new MyClass(...)? Nope. new does some things behind the scenes that you cannot replicate without calling new. e.g.,

var mine = {};
for(var i in MyClass.prototype) {
mine[i] = MyClass.prototype[i];
}
MyClass.apply(mine,'foo','bar');
// mine instanceof MyClass == false

So, what we have is an instance that is almost, but not quite identical to an instance created with new. If you know that the object will only be duck typed, then this is good enough. However, if it's possible that it might end up in an instanceof or have some other low level type check, this isn't good enough. The final trick that you need is new:

function newInstance(type,args) {
var f = function() {};
f.prototype = type.prototype;
var o = new f;
return type.apply(o,args) || o;
}

By creating a no-arguments function with the same prototype, we can safely use new to get the prototype copying, and then call the constructor using apply. instanceof type (and other checks, like prototype.constructor) will return true, and the new instance will walk and talk like a duck of MyClass.