More fun with Jasmine, Sinon and JavaScript

By Kenneth 'RabidDog' Clark at January 26, 2012 22:48
Filed Under: Code, JavaScript, Test Driven Development

Once again delving into front end JavaScript development (which I might add is not all that fun Sad smile) I have started to gather a few tid bits on good sites to have a look at. Before I post that I want to make a few points on the whole JavaScript world and why I find it to be so annoying to work with.

 

A few general trends I have noticed in the web development world is that the idea of using solid architectural practises is often undermined by the need for fancy front end user experiences. This leads to a very dangerous situation were we sacrifice the integrity of backend services to facilitate fancy front end experiences. This being said, I must admit, that I do like the trend developing in the JavaScript development community to implement test cases. Lets hope this trend continues!

 

The one thing that really, and I mean REALLY, frustrates me around the JavaScript language is the lack of structure. While this might be a plus for some people, it is highly frustrating me. Why has the ECMA specification not allowed for a simple import function? All other major platforms and languages allow you to import reference files. Yes, I know you can merge them, minify them and then wrap them in cheese but why should you have to? I know that this decreases HTTP traffic in certain instances but it is a pain in the rectum to develop for. Some sort of import directive is long over due in JavaScript. Why should my HTML pages contain script reference tags? This doesn’t fit in with the view knowing nothing about the application layer. With unobtrusive JavaScript becoming big this is a serious flaw in the design. I know there are ways to get round all this but all mechanism involving referencing files is contrived.

 

That single word sums up my feelings on JavaScript development, it is contrived. That an the lack of support by any major IDEs is also painful. Yes, you should know how to do this without the help of an IDE but that is like telling a dentist to use a handle drill because an electric drill is too helpful.

 

The lack of standards regarding engineering practises in JavaScript, the custom JavaScript engines found in all major browsers and a few other things still make JavaScript development a “dark art”. I take my hat off to good, productive JavaScript developers, you guys truly have a gift. I am also left wondering who long it will be before JavaScript grows up.

 

Anyways if you looking to get into the whole JavaScript TDD and MVC boat I would highly recommend that you check out a fantastic set of write ups by Jim Newbery over at tinnedfruit.com.

 

http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html

 

Well here is to JavaScript growing up!

JavaScript Hashmap and MVC 3

By Kenneth 'RabidDog' Clark at September 22, 2011 23:00
Filed Under: C#, Code, JavaScript, Web

I was fiddling with an idea that allowed rows to be dynamically added to an html page and deleted off the page. This became a bit tricky because I couldn’t identify the row I wanted to get rid of.

 

Eventually what I ended up doing was maintaining a list of the rows in a JavaScript object that functioned the same as the hash map and as opposed to deleting one row at a time I would remove the entire list from the page and re render it. The reason for this is when submitting arrays to an MVC 3 controller based on a strongly typed model you have to name the hidden input fields sequentially. Something like this:

 

<input type="hidden" id="EventList_0_SomeId" name="EventList[0].SomeId"  value="myid" />
<input type="hidden" id="EventList_0_Capacity"  name="EventList[0].Capacity"  value="25" />

 

As you probably gathered the next one would increment the 0 in the id and the 0 in the name to 1. The next one 2 and so on and so forth.

 

<input type="hidden" id="EventList_1_SomeId" name="EventList[1].SomeId"  value="myid" />
<input type="hidden" id="EventList_1_Capacity"  name="EventList[1].Capacity"  value="25" />

<input type="hidden" id="EventList_2_SomeId" name="EventList[2].SomeId"  value="myid" />
<input type="hidden" id="EventList_2_Capacity"  name="EventList[2].Capacity"  value="25" />

<input type="hidden" id="EventList_3_SomeId" name="EventList[3].SomeId"  value="myid" />
<input type="hidden" id="EventList_3_Capacity"  name="EventList[3].Capacity"  value="25" />

Just as a pointer, the name and the id of the input have to be declared or the MVC 3 controller will not resolve the values. The above example is a model that contains a list of objects that contain a property called SomeId and Capacity. If you do it the way I have illustrated above, it will resolve into a nice object representation in the controller that you can manipulate.

 

The Hashmap declaration:

function Map()
{
    // members
    this.keyArray = new Array(); // Keys
    this.valArray = new Array(); // Values
        
    // methods
    this.put = put;
    this.get = get;
    this.size = size;  
    this.clear = clear;
    this.keySet = keySet;
    this.valSet = valSet;
    this.showMe = showMe;   // returns a string with all keys and values in map.
    this.findIt = findIt;
    this.remove = remove;
}

function put( key, val )
{
    var elementIndex = this.findIt( key );
    
    if( elementIndex == (-1) )
    {
        this.keyArray.push( key );
        this.valArray.push( val );
    }
    else
    {
        this.valArray[ elementIndex ] = val;
    }
}

function get( key )
{
    var result = null;
    var elementIndex = this.findIt( key );

    if( elementIndex != (-1) )
    {   
        result = this.valArray[ elementIndex ];
    }  
    
    return result;
}

function remove( key )
{
    var result = null;
    var elementIndex = this.findIt( key );

    if( elementIndex != (-1) )
    {
        this.keyArray = this.keyArray.removeAt(elementIndex);
        this.valArray = this.valArray.removeAt(elementIndex);
    }  
    
    return ;
}

function size()
{
    return (this.keyArray.length);  
}

function clear()
{
    for( var i = 0; i < this.keyArray.length; i++ )
    {
        this.keyArray.pop(); this.valArray.pop();   
    }
}

function keySet()
{
    return (this.keyArray);
}

function valSet()
{
    return (this.valArray);   
}

function showMe()
{
    var result = "";
    
    for( var i = 0; i < this.keyArray.length; i++ )
    {
        result += "Key: " + this.keyArray[ i ] + "\tValues: " + this.valArray[ i ] + "\n";
    }
    return result;
}

function findIt( key )
{
    var result = (-1);

    for( var i = 0; i < this.keyArray.length; i++ )
    {
        if( this.keyArray[ i ] == key )
        {
            result = i;
            break;
        }
    }
    return result;
}

function removeAt( index )
{
  var part1 = this.slice( 0, index);
  var part2 = this.slice( index+1 );

  return( part1.concat( part2 ) );
}
Array.prototype.removeAt = removeAt;

 

The usage is just as simple. Include the JavaScript file and then:

var map = new Map();

map.put("key", value);
map.remove("key");

//etc

 

A really nice feature is that it does not duplicate keys but performs an “update” on the object at that key. So if you want to retrieve all the keys you can do something like this:

 

for (var i = 0; i < hashMap.keyArray.length; i++) {
    var value = map.valArray[i];
    var key = map.keyArray[i];
    console.log(key, value.toSource());
}

 

 

I found the Hashmap declaration over here http://freecode-freecode.blogspot.com/2007/06/hashmap-object-in-javascript-like.html

 

Some other interesting tid bits on the MVC embedded arrays, lists and editors for:

Internet Explorer 8 and JQuery 1.6.x

By Kenneth 'RabidDog' Clark at September 21, 2011 13:49
Filed Under: Code, JavaScript, Web

Recently I launched a new site for a friend http://www.motoschool.co.za. Everything was working really well till the site was opened in Internet Explorer 8.

 

So I set about trying to figure out what was going on. Every time a link was opened the tab would crash and recover. My initial thoughts where that something was wrong with the JavaScript. So I started commenting out code to try and establish what was going on. Then I thought there might be something wrong with the CSS that was causing the tab to crash. I went around in circles for about an hour till I decided to scrap everything.

 

I commented out all the styles and scripts and the site stopped crashing the tab. Then I started adding back the references one by one till the browser crashed again. This happened as soon as I included the JQuery 1.6 min file. I couldn’t figure out what to do till a ray of sunshine hit me and I thought about the JavaScript parsing engine in Internet Explorer 8. What if the parsing engine was failing on something and causing so sort of memory leak or overflow?

 

So I proceeded to download the uncompressed version of the JQuery library and added it. Holding my breath, I refreshed the page and clicked around a few times. The site was now working!

Unobtrusive label to textbox association using JQuery

By Kenneth 'RabidDog' Clark at August 22, 2011 21:33
Filed Under: Code, JavaScript, Work

Well things just seem to be getting easier and easier. Next up I have a form that I wanted to try the concept of unobtrusive JavaScript. The form is relatively simple containing two labels and text boxes for a first name and a last name. Here we have the form in Razor (MVC3)

 

   1: <form id="registrationForm">
   2: @Html.LabelFor(x => x.FirstName)
   3: @Html.TextBoxFor(x => x.FirstName)
   4: <br />
   5: @Html.LabelFor(x => x.LastName)
   6: @Html.TextBoxFor(x => x.LastName)
   7: </form>

Then I started experimenting with the page JavaScript is located in a separate file. So it would be included in a script tag. It actually turned out way simpler than I initially thought.

 

Here is my first iteration of the JavaScript file

   1: /**
   2: * Configure the function to handle the label insertion into
   3: * the text areas
   4: */
   5: $(function () {
   6:     $('#registrationForm label').each(function (i) {
   7:         var label = $(this);
   8:         var textBoxId = "#" + label.attr("for");
   9:         var text = label.text();
  10:         var textBox = $(textBoxId).val(text);
  11:  
  12:  
  13:         textBox.focus(function () {
  14:             if (this.value == text) {
  15:                 this.value = "";
  16:             }
  17:         })
  18:         .blur(function () {
  19:             if (this.value == "")
  20:                 this.value = text;
  21:         });
  22:  
  23:         label.hide();
  24:     });
  25: });

And that, honestly, was that. Of course looking at that I couldn’t help but feel it better to wrap it in a function so I don’t have to replicate that code on every form. So this is what I ended up with in my handy little helper class:

   1: function Helper() { }
   2:  
   3: Helper.processFormLabels = function (formId) {
   4:     var query = "#" + formId + " label";
   5:     $(query).each(function (i) {
   6:         var label = $(this);
   7:         var textBoxId = "#" + label.attr("for");
   8:         var text = label.text();
   9:         var textBox = $(textBoxId).val(text);
  10:  
  11:  
  12:         textBox.focus(function () {
  13:             if (this.value == text) {
  14:                 this.value = "";
  15:             }
  16:         })
  17:         .blur(function () {
  18:             if (this.value == "")
  19:                 this.value = text;
  20:         });
  21:  
  22:         label.hide();
  23:     });
  24: }

Then the document on load script looks like this

   1: /**
   2: * Configure the function to handle the label insertion into
   3: * the text areas
   4: */
   5: $(function () {
   6:     Helper.processFormLabels("registrationForm");
   7: });

Include all relevant JavaScript files and viola! Off you go.

ASP.NET, MVC3, Razor and adding scripts where they supposed to go

By Kenneth 'RabidDog' Clark at August 22, 2011 20:12
Filed Under: C#, Code, JavaScript, Work

I was always under the impression that the HEAD of an HTML document contained the SCRIPT tags. Call me old fashioned but I actually quiet like it that way.

 

Then I came across a discussion at http://stackoverflow.com/questions/1213281/does-javascript-have-to-be-in-the-head-tags concerning this very thing. Some say HEAD, some say BODY and some say WHERE_EVER_YOU_WANT. I then went and confirmed the HEAD and BODY issue at http://www.w3.org/TR/html4/interact/scripts.html

 

I can see validity in the arguments but with the advent of the unobtrusive JavaScript model I am beginning to wonder if arguments like this are really valid any longer. I also question whether being able to see the page before being able to use it is such a good idea. I personally would prefer the user is not able to see anything till the code to assist them has loaded. Again with the unobtrusive JavaScript stuff, my argument is also flawed.

 

Either way, I decided I wanted a mechanism where I could add the path to a collection and it would be inserted into the page in a central location, top or bottom, HEAD or BODY.

 

So I had a look at the ViewBag now offered in MVC 3 and decided it would be the best place to have a collection like this. Seeing as it is dynamic and available on all pages it made the most sense. I didn’t want to have to go and create a store to store the collection in and then query it before rendering, I just wanted it to work so below is what I came up with:

   1: //Inside the view page
   2: @{
   3:     ViewBag.Title = "MyPage";
   4:     ViewBag.Scripts = new List<String> { "Pages/MyPage.js" };
   5: }

Then in the master or layout page you can quiet easily do this:

   1: <head>
   2:     <title>@ViewBag.Title</title>
   3:     <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
   4:     <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
   1:  
   2:     @{
   3:         if (ViewBag.Scripts != null) {
   4:             foreach (var script in ViewBag.Scripts) {
   5:         <script src="@Url.Content("~/Scripts/" + @script)" type="text/javascript">
</script>
   5:             }
   6:         }
   7:     }
   8: </head>

This neatly renders the the script tags into the HEAD section (where I wanted it).

 

I then went and created an html helper to do this so I could use without all the verbose checking being embedded in the view/layout page.

   1: using System.Collections.Generic;
   2: using System.Text;
   3: using System.Web.Mvc;
   4:  
   5: namespace System.Web.Helpers {
   6:     public static class HtmlHelper {
   7:  
   8:         const string ScriptTag = "<script src=\"{0}\" type=\"text/javascript\"></script>";
   9:         private const string PathPrefix = "~/Scripts/{0}";
  10:  
  11:         /// <summary>
  12:         /// Inserts the scripts. If using a viewbag remember to cast the input property
  13:         /// </summary>
  14:         /// <param name="html">The HTML.</param>
  15:         /// <param name="scripts">The scripts.</param>
  16:         /// <param name="urlHelper">The URL helper.</param>
  17:         /// <returns></returns>
  18:         public static IHtmlString InsertScripts(this System.Web.Mvc.HtmlHelper html, IList<String> scripts, UrlHelper urlHelper) {
  19:  
  20:             if (scripts == null)
  21:                 return new HtmlString(String.Empty);
  22:  
  23:             var output = new StringBuilder();
  24:  
  25:  
  26:             foreach (var script in scripts) {
  27:                 output.AppendFormat(ScriptTag, urlHelper.Content(String.Format(PathPrefix, script)));
  28:             }
  29:  
  30:             return html.Raw(output.ToString());
  31:         }
  32:     }
  33: }

Which means the call in the view or layout page is reduced to

   1: <head>
   2:     <title>@ViewBag.Title</title>
   3:     <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
   4:     <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
   5:     @Html.InsertScripts((IList<String>)ViewBag.Scripts, Url);
   6: </head>

 

Nice and clean (well kinda)

JSON serialization and deserialization

By Kenneth 'RabidDog' Clark at August 21, 2011 23:46
Filed Under: Code, JavaScript, Methodologies, Web

More JSON goodness! While doing my tests using the Jasmine framework I started noticing in my code that the data I was submitting needed to be serialized from a JavaScript object to a JSON representation. One would think that this might be real easy but alas, it seems that only the newer versions of the browsers implement the stipulated methods to serialize the object.

 

Even everybody's favourite JavaScript library, JQuery, doesn’t implement a mechanism to do this. (check out http://stackoverflow.com/questions/2277405/json-stringify-missing-from-jquery-1-4-1 for further discussions and http://api.jquery.com/category/utilities/ for confirmation)

 

So I started going through posts and pointers from other developers. The first set of posts I read used a customised mechanism of serializing the object (http://blog.stchur.com/2007/04/06/serializing-objects-in-javascript/ and http://www.sitepoint.com/javascript-json-serialization/). While this looks very cool I wasn’t willing to replicate the functionality just in case I missed something.

 

Then I came across http://www.json.org/js.html which defined a mechanism to do what I needed but I still wasn’t convinced. So after a while of reading I came across (http://stackoverflow.com/questions/2277405/json-stringify-missing-from-jquery-1-4-1 –> last post which points to http://code.google.com/p/jquery-json/). HOOAH! This did exactly what I wanted and wrapped it up nicely.

 

So off I go implementing the methods using the functions provided in jquery-json. The more I did, the less I liked it. The code was starting to smell a bit. So instead of doing the the following over and over and over:

   1: //Convert to JSON string
   2: var jsonString = $.toJSON(myObject); 

I decided it would probably be better to wrap the entry point into this mechanism into a single entry point for my application. Allowing me to swop out the implementation if need be without having to remove/rename a stack of references. So it ended up looking like this.

   1: //Back to my handy helper class :)
   2: function Helper() { }
   3:  
   4: //Convert JSON to object
   5: Helper.getObject = function (jsonString) {
   6:     return $.evalJSON(jsonString);
   7: }
   8:  
   9: //Convert object to JSON
  10: Helper.getJson = function (object) {
  11:     return $.toJSON(object);
  12: }

 

A great deal of people might think this is over complicating it, adding an unnecessary layer etc. I would argue that it decouples my dependency on the jquery-json library or at least isolates it’s usage to one location. As pointed out previously, should I need to call a different library I would only have to change it in one file. Nothing really fancy about the code but might spark other ideas. The jquery-json library also implements a secureEvalJSON which seems to prevent possible abuse of the JSON returned. With that being said I am going to change my getObject implementation to use it Smile

 

References:

http://code.google.com/p/jquery-json/

http://www.metaltoad.com/blog/using-jsonp-safely – interesting post on JSONP security

Jasmine and mock AJAX

By Kenneth 'RabidDog' Clark at August 20, 2011 21:20
Filed Under: Code, JavaScript, Test Driven Development

Things just keep getting better for me today Smile. Having had a great deal of fun with the nHibernate search I stumbled across a really neat JavaScript testing framework call ‘Jasmine’. Now not to go through the whole blah blah of what ‘Jasmine’ is I would recommend you Google it. Plenty of references to the project there (http://www.mediafly.com/content/exploring-jasmine-bdd-framework-javascript for starters!)

 

What I would like to point out is the AJAX mock requests and responses. One painful thing about testing JavaScript is the need to manually navigate the site/pages and debug the responses. Personally I like a TDD approach and wanted to try doing the JavaScript development using TDD.

 

While getting started with ‘Jasmine’ is very simple I did fiddle for an hour or so trying to assimilate the mechanism I was to use in mocking AJAX responses. So below I have listed the steps required to get a basic round trip going. This would reside in the *Spec.js file.

 

   1: describe("Application", function () {
   2:     var application;
   3:     var profile;
   4:  
   5:     beforeEach(function () {
   6:         application = new Application();
   7:         profile = new Profile();
   8:         spyOn($, "ajax").andCallFake(function (params) {
   9:             params.success('{"IsRegistered" : true}');
  10:         });
  11:     });
  12:  
  13:     it("should be able to register with the site", function () {
  14:         profile.firstName = "firstname";
  15:         profile.lastName = "last";
  16:         profile.email = "email@domain.com";
  17:         profile.birthDate = new Date("2011-04-01");
  18:  
  19:         application.register(profile);
  20:         expect(profile.isRegistered).toEqual(true);
  21:     });
  22: });

 

And to quickly run through it:

  • beforeEach is the same as SetUp in your standard unit testing frameworks, so here you setup your test case.
  • spyOn is a method declared in the ‘Jasmine’ framework and dictates which class it should ‘spyOn’ and what method it should spyOn in that class.
  • andCallFake is the mechanism that reroutes the AJAX request to the anonymous method declared inside it.
  • params relates back to the jQuery AJAX definition. Via this we can execute the success method and pass in the response data we have manually defined.

 

Very cool. As this is my initial exploration into ‘Jasmine’ I might very well have got it wrong or there might be a smarter way of doing this but I thought I would share it anyways!

 

References:

JavaScript Associative Array

By Kenneth 'RabidDog' Clark at August 20, 2011 19:35
Filed Under: Code, JavaScript

Although an associative array doesn’t technically exist in JavaScript it can be achieved via

   1: var myArray = new Array();
   2: myArray["index1"] = "Value1";
   3: myArray["index2"] = "Value2";

This is all fine and dandy till you realise that the length property will always return zero ( 0 )

   1: //always displays zero
   2: alert(myArray.length);

This can be highly annoying considering the fact that you might need to do work based on whether or not the array has any values. The only solution I could find is to create a static helper method. So in my OO nature I created:

   1: function Helper() { }
   2: Helper.arraySize = function (associativeArray) {
   3:                                 var count = 0;
   4:                                 for (var i in associativeArray) {
   5:                                     count++;
   6:                                 }
   7:                                 return count;
   8:                             }

So now if I need to check the length of an “associative array” I can do so via:

   1: // Displays 2
   2: var size = Helper.arraySize(myArray);
   3: alert(size);

Might seem like a long way round but it is the only method I found thus far that facilitates my use case. Don’t forget to include the JS file if you have put it in a separate file Winking smile 

References:

Technorati Tags:
Windows Live Tags: JavaScript
WordPress Tags: JavaScript



I am South African. Always have been always will be. I love my country. I love my wife and two children.


I also really enjoy solving problems. I currently work as a Software Architect exploring new solutions for business problems. Having been round the block a few times I enjoy showing new developers how best to solve problems, how to find answers and how to approach solution development.


In my spare time I enjoy riding my super bike, training in Systema and horsing around with my family.


Month List

Visitors

Twitter Feed

20. February 21:10
@telkomsa saying a pending R4.2 billion fine could sink them, I say sink them! Tired of paying for (no) service.

19. February 22:39
@telkomsa congratulations! This is a new record regarding no/intermittent service! Just over 2 months tossers! And I still pay for it

6. February 18:01
Unit tests don't check if code works. They PROVE the code works!

12. January 23:34
@Annaling horrific. People like that should face sever punishment. Unless of course they tried to find the cat :(