Monthly Archives: December 2012

Learn Javascript – the Language Itself

One of the worst pieces of advice that I have ever received was from an architect / team leader which I used to work with. He told me,
“Don’t waste your time learning Javascript. Just learn one of the modern libraries like jQuery.”

As you can probably figure out, this guy was a bad advice machine, with terrible judgment to boot.

In a Douglas Crockford video I once watched, he lamented that one of the big problems which plagued Javascript was that developers started writing it without actually learning it first. As I trust the great Douglas Crockford over the aforementioned incompetent architect, I decided to learn Javascript.

The reason I bring this up is because the other day I was reading the jQuery API documentation about the map() function (refreshing my memory – it had been a while). In the examples section, the following code was set out:

...
<script type="text/javascript">// <![CDATA[
$.fn.equalizeHeights = function() {
  var maxHeight = this.map(function(i,e) {
    return $(e).height();
  }).get();

  return this.height( Math.max.apply(this, maxHeight) );
};

$('input').click(function(){
  $('div').equalizeHeights();
});
// ]]></script>

If I was not fluent in javascript, I would not have understood the following fragment of code:

Math.max.apply(this, maxHeight)

The apply method is quite particular to javascript. Sure, I could have Googled that code and just chucked it in my project to get it working. But I wouldn’t have a clue why it works. And many developers I know aren’t even aware of the apply method, let alone what it does. Don’t be surprised by that. Really!

As it turned out, the architect I mentioned above did not understand Javascript or AJAX at all. This became apparent in various team discussions, and made for some great giggling amongst the junior developers.

So listen to Crockford. Learn Javascript! With the HTML 5 stuff and the advent of client-side, data-binding frameworks, developers will be writing more Javascript than they ever have before.

Javascript Variables Set Dynamically Server-side

I have been knocking this post around in my head for a couple of days now. It all started when I read this great post about how to use the jQuery DatePicker widget with ASP.NET MVC. In that post, the Stuart Leeks “hard-wires” the date format to be the UK format for the date-picker and leaves it to the reader to dynamically set that format as an exercise.

I recall my times in Webforms where the task of rendering ClientIDs for Server controls in Javascript was quite challenging. A lot of people wrote horrible code in their mark-up like:

'<%= SecurityCheckCompleteCheckBox.ClientID %>'

Ugh, grotesque. (I can’t count the number of dodgy forum posts which put that syntax forward as a solution). Guys with more enterprise experience wrote elegant code like this.

In MVC, it is a lot easier to accomplish this, given the fact that HTML ids are not generated for you by the ASP.NET runtime. But, we still may come up against a situation whereby we want to use a variable in a javascript file which you want to dynamically set at runtime.

For example, take the date format for the DatePicker in the blog post referred to above. There, the javascipt file has some script like this:

    $('.date').each(function () {
        var minDate = getDateYymmdd($(this).data("val-rangedate-min"));
        var maxDate = getDateYymmdd($(this).data("val-rangedate-max"));
        $(this).datepicker({
            dateFormat: "dd/mm/yy",  // UK format hard-coded
            minDate: minDate,
            maxDate: maxDate
        });
    });

The problem to solve is that you want to use a dynamically generated javascript variable so that the code looks more like this:

    $('.date').each(function () {
        var minDate = getDateYymmdd($(this).data("val-rangedate-min"));
        var maxDate = getDateYymmdd($(this).data("val-rangedate-max"));
        $(this).datepicker({
            dateFormat: SvrSideVariables.DateFormat,  // format set server-side
            minDate: minDate,
            maxDate: maxDate
        });
    });

As you are aware, you can’t write any kind of C#/server-side code inside a javascript file. And although you can do it in a script tag in the markup, script tags containing javascript content are evil, unless dynamically generated. The separation of presentation from behaviour requires that there be no javascript in the markup, unless it is just a script element pointing to an external javascript file.

What follows is a very basic solution to this problem. There are many approaches one could take to attacking this problem.
Lets set the dateformat variable in the web.config file, so we can change it without having to recompile.

  <appSettings>
    <add key="ClientValidationEnabled" value="true"/> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>
    <add key="DateFormat" value="dd/mm/yy"/>
  </appSettings>

Then, we’ll just use a simple custom HtmlHelper to render that variable in a script tag, which we will add to the head section of our document:

        public static MvcHtmlString CreateServerSideVariables(this HtmlHelper helper, string variable)
        {
            // Create tag builder
            var builder = new TagBuilder("script");

            // Add attributes
            builder.MergeAttribute("type", "text/javascript");

            // We want a namespace, because as the great Douglas Crockford said, the Global namespace is eeevil.
            builder.InnerHtml = "if(typeof SvrSideVariables == 'undefined') var SvrSideVariables = { }; SvrSideVariables.DateFormat = '" + variable + "';";

            // Render tag.
            return MvcHtmlString.Create(builder.ToString(TagRenderMode.Normal));
        }
    }

Such a script tag is fine, because it keeps the markup which you have to maintain clean (no mixing of behaviour and presentation) and it is done dynamically at run-time. Make sure you add that element before your custom script, so the variable “SvrSideVariables.DateFormat” will be available for use by your custom script which uses it to set the date format for your datepicker.

Finally, use the helper (in the Edit.cshtml file):

@section ServerSideVariables{
    @Html.CreateServerSideVariables(ConfigurationManager.AppSettings["DateFormat"])
}

And of course in the _Layout.cshtml:

@RenderSection("ServerSideVariables", false)

That’s one of several approaches.

Get the code, which just augments the code from the original article: