TypeScript patterns: Controller

by dotnetnerd 7. August 2017 11:45

The next pattern I want to take a look at, that is fundamental to how many JavaScript applications are structured, is the Controller pattern.

There are different definitions for what a Controller is on the client, depending on what framework people are used to working with. As you may know I often recommend not using a framework, but I go with the definition that a controller encapsulates the UI logic for a part of a web page. A common practice is to have controllers take the html element that it works on as the first constructor argument, followed by dependencies (services and other controllers) and possibly an options object. This will resemble what you are likely doing if you are writing eg. an MVC application in ASP.NET MVC or WebAPI. In much the same way, this allows you to pass in dependencies, and keep the controller free of hardcoded dependencies.

More...

User Experience on the web - moving beyond jQuery

by DotNetNerd 31. August 2011 21:23

Providing a customized high quality user experience is becomming increasingly important on the web. It is no longer enough to provide information and functionality, but it also has to look and feel nice in a way that contributes in building the company brand. To do this we needed to shift some of the focus toward what is running on the client.

HTML5

Fattening up the client

At first the search for fatter and richer clients lead us to focus on Flash or Silverlight. While providing a rich design experience this also comes with its own set of limitations. Limitations such as requiring users to install a browser plugin that in turn removes the browser experience with linking and the options to copy text and images. Since then we have come full circle so we once again use *drumroll* JavaScript to power applications. With the emergence of HTML5 and CSS3 that will be running across computers, tablets and phones it looks like JavaScript and friends will continue to play a key role in developing tomorrows applications.

Curing the JavaScript headacke

A few years ago I - like most developers at the time - did not like JavaScript. We saw it as a necessary evil to allow validation, and something we needed to fight with once in a while to show/hide elements on webpages. JavaScript suffered from a range of illnesses such as browser incompatibility, performance issues, lack of widely adopted development practices and a rap for being brittle.

browsers

Along came jQuery - a JavaScript library that did a good job at shielding the developer from browser incompatibility while providing a simple API for doing DOM manipulation and providing structure for plugins to be built. The library has since become so popular that some developers talk about "writing jQuery" rather than JavaScript.

Thanks to the need for better user experiences, jQuery and in no small part the technological advances in the browser reguarding performance, we developers spend more and more time writing JavaScript. While jQuery has helped a great deal there are still areas where working with JavaScript seems unstructured and primitive in reguards to expressiveness and robustness. So lets look at some options we have to accomodate those needs.

Underscore - the functional tie

Underscore is a JavaScript library that prides itself in being "the tie to go along with jQuery's tux". Basically it provides a utility-belt for doing functional-style programming in JavaScript. This is important because regular JavaScript constructs tend to be so low-level that "what" you are doing is drowning in "how" you are doing it. With underscore you get quite of bit more expressiveness, making code easier to read and maintain. Besides the functional core underscore also provides a way through some shortcommings of JavaScript - like binding functions to objects - and it has templating capabilities.

This sample shows off some of the functional capabilities, as well as how to use templates.

var sumOfEvens = _(_.range(1, 50))
.chain().map(function(number) {return number * 2;})
.reduce(function(sum, number) {return sum + number;})
.value();

var template = _.template("The sum of even numbers between 1 and 100 is <%= sum %>");
console.log(template({sum : sumOfEvens}));

"Grow a spine"

Spine and Backbone are two very similar frameworks that provide structure to applications written in JavaScript through an MVC pattern. In more and more scenarios each page can be seen as a small application by itself, so structure is becoming as important as it is on the server. Spine is the smallest of the two, so I will focus on that - but mostly you can assume that Backbone works pretty much the same way. Fundamentally they allow you to work with classes so you get a way to do inheritance. Building on that you can create models for persisting data and controllers (which are called views in backbone) that give you a structure for defining events and functions. To support this the libraries also have functions for working with events and a way to handle routing with hashtags.

This sample shows how to work with a model that is persisted to local storage, how to handle events and how to respond to routing.

var Contact = Spine.Model.setup("Contact", ["id", "first_name", "last_name"]);
Contact.extend(Spine.Model.Local); //Saves to local storage

var eric = Contact.init({id: 1, first_name: "Eric", last_name: "Cantona"});
eric.bind("save", function(){ console.log("Saved!"); });
eric.save();

var ryan = Contact.init({id: 2, first_name: "Ryan", last_name: "Giggs"});
ryan.save();

var App = Spine.Controller.create({
    init: function(){
        this.routes({
            "/users/:id": function(id){
                var c = Contact.find(parseInt(id));
                console.log("Name: " + c.first_name + " " + c.last_name);
            },
            "/users": function(any){
                Contact.each(function(c){
                    console.log("Name: " + c.first_name + " " + c.last_name)
                });
            }
        });
    },
    events: {"click input": "click"},
      click: function(event){
        var c = Contact.find(1);
        console.log("Name: " + c.first_name + " " + c.last_name);
      }
}).init({el: $("#Players")});

Spine.Route.setup();

I have previously written a bit about KnockoutJS, which can be seen as an alternative to using Spine or Backbone. Rather than provding a MVC-like structure Knockout allows you to work with a MVVM model with two-way databinding. I will not try and argue that the Spine/Backbone or KnockoutJS approach is "better", but leave you with the typical developer cop out "it depends". The design decision that you face really is, what brings greater value in your case, modularity, eventhandling and routing or two-way databinding, templating and dependency tracking?

"Testing testing 1-2-3 - is this thing on?"

The last piece of the puzzle is to introduce testing which should help us write and maintain more robust applications. QUnit is a simple unit testing framework that is popular amongst the people who work with jQuery and plugins for jQuery. QUnit lets you group tests into modules, so you get a nice overview when you run the testsuite.

add = function(a, b) {return a + b};

module("Math module");

test("addition", function() {
  expect(2);
  equal( add(2, 2), 5, "failing test" );
  equal( add(2, 2), 4, "passing test" );
});

jasmine_logo

For those who prefer a BDD style framework Jasmine is a popular choice. Besides having a different style Jasmine also has functionality to work with spies, for some more advanced testing scenarios. Both frameworks provice a clean and easy to read syntax, so choosing between the two comes down to taste or if there is some small feature in either that you like.

function Calculator() {}

Calculator.prototype.add = function(a, b) {
  this.log(a + " + " + b + " = " + (a + b));
  return a+b;
};

Calculator.prototype.log = function(text) {
  console.log(text);
};

describe("Calculator", function() {
  var sut;
 
  beforeEach(function() {
    sut = new Calculator();   
  });

  it("should be able to add", function() {
    var result = sut.add(2, 2);
    expect(result).toEqual(4);      
  });
 
  it("should log what is added", function() {
    spyOn(sut, 'log');
    var result = sut.add(2, 2);
    expect(sut.log).toHaveBeenCalledWith("2 + 2 = 4");
  });
});

MiniMe–opinionated JavaScript and CSS bundling

by dotnetnerd 6. July 2011 20:03

Why MiniMe?

For a while I have been using SquishIt to minify, bundle and version JavaScript and CSS files – and to a large extent it did a good job. However on a number of occations I ran into a group of scenarios where it just didn’t quite do enough for what I wanted. So when I was starting a new project and ran into the same issues again, I decided to take a look at making my own.

The basic idea behind MiniMe is that it should make it easy to bundle JavaScript and CSS files across masterpages, usercontrols etc. with the option to control how they are sorted, and end up with one file that is minified and versioned. It should also be easy to introduce into an existing project, with a minimal amount of refactoring, and lastly it should be easy to adhere to best practices and inject the script tag at the very bottom of the html page.

These are the requirements that I run into again and again, so I wanted a tool that did exactly that.

Getting started

To make it as easy as possible I made a nuget package, so all you need to get off the ground is to search for MiniMe in the package manager and hit install.

Building a complete file

Now you have access to the classes MiniJavaScriptBuilder and MiniStyleSheetBuilder, that can be used to build either a JavaScript or CSS file. The approach is similar, so from how on I will just show the JavaScript case. Using either one you can build a collection of files by calling Add or AddToRequest, which takes a path to the file you wish to add. The difference is that Add is local to the instance of the builder, where the ToRequest version is stored for the request across any number of builders. Both methods return the builder instance, so calls to Add/AddToRequest can be chained.

@{ new MiniMe.MiniJavaScriptBuilder()
    .AddToRequest(Url.Content("/scripts/myFirstScriptFile.js"))
    .AddToRequest(Url.Content("/scripts/mySecondScriptFile.js"), 1)         
    }

When using AddToRequest you can optionally pass an index as a second parameter. Files with a lower index are included before those with a higher index – allowing files that are added from usercontrols to run after those added in the masterpage.

Manually rendering a combined file

When all your files have been added you can call either Render or RenderForRequest, which will behave differently depending on if you have turned debug on in web.config or not. If you are in debugmode there is simply rendered a reference to each file, allowing you to debug like you are used to. If you are NOT in debugmode the files that were added will be combined and saved to the path you pass to the method. Writing a # as part of the path will enable versioning, so the # is replaced by a hashvalue of the filecontent. Versioning will make sure the filename changes when any of the files are changed, so caching does not prevent your users from getting any changes that you have made.

@{ MvcHtmlString.Create(new MiniMe.MiniJavaScriptBuilder()
.AddToRequest(Url.Content("/scripts/myFirstScriptFile.js"))
.AddToRequest(Url.Content("/scripts/mySecondScriptFile.js"), 1)
.RenderForRequest(Url.Content("~/Scripts/Site_#.min.js")))
}

Automatically injecting a combined file

Working with complex layouts can be a pain, because you have to take into account the order the usercontrols are rendered, and you will have duplication of code to render the files. To solve this MiniMe comes with an HttpHandler that will handle the rendering for you. This means that files that are added to the request, will be bundled, the combined JavaScript is referenced from the very bottom of the page and the Stylesheet is referenced from the header. All you have to do is add the HttpModule.

<system.webServer>
    <modules>
        <add name="MiniHttpModule" type="MiniMe.MiniHttpModule, MiniMe"/>

By default the HttpModule renderes the files to “/Scripts/Site_#.min.js” and “/Content/Site_#.css” – this can be overwritten using appSettings

<appSettings>
    <add key="MiniJsRelativePath" value="/Scripts/OtherSite_#.min.js"/>
    <add key="MiniCssRelativePath" value="/Content/OtherSite_#.min.css"/>

Create .min.js versions of all JavaScript files

In some cases you might want to have MiniMe generate .min.js versions for any files that have not yet been minified. This will also give you a slight performance boost, because MiniMe will not have to do the minification on the fly when files are combined. It is important to note that MiniMe will only make minified versions when no minified version already exist. Personally my preference is to do it when not running in debugmode, because then I won’t have to delete the minified versions when I make chances, in order for MiniMe to generate new ones.

if (!HttpContext.Current.IsDebuggingEnabled) new MiniGenerator().EnsureMiniVersions("/Scripts");

Go to the source to gain more insight or contribute

MiniMe is hosted on bitbucket, so if you wish to see how it works, or if you want to contribute please don’t hesitate. The first version was focused around the features I felt were missing, but there are undoubtedly other scenarios that can provide value.

Mama said knock you out!

by dotnetnerd 20. May 2011 13:35

In my last post I looked at how WCF Web API plays well with JQuery Templates. A former colleague of mine questioned if it could be used in all scenarios. This is a rather broad question, but I do think it can be used for most of your templating needs.  So in this post I will give an example of what can be done just with templates – and then I will take a look at KnockoutJS to make my templating scenario even sweeter.

More...

Yearning for some learning?

by DotNetNerd 1. April 2011 19:57

A piece of advise that is often given to developers who want to keep improving, is to learn a new programming language every year. I mostly think it holds true if you try to learn a new paradigme – because just learning new syntax won’t really get you anywhere.

Koans

One way of learning a new language is of course to buy a book or two, and start reading and doing some samples and small applications. Another way of going about it is to try some of the koans, interactive interpreters and introductory guides that can be found online.

1000_jaws_koan

More...

My Ajaxy JavaScript stack

by DotNetNerd 24. January 2010 12:12

I have been working primarily with ASP.NET MVC for a little over a year now, and this has prompted me to do quite a bit more Ajaxy functionality. So while doing this I have been looking at quite a few Ajax/Javascript libraries.

As most other developers I have been swept away by JQuery, which by far is the most important component when I am doing Ajax and manipulating the html DOM - see cheatsheet. Besides making a lot of these things easier, it also provides a wide variety of plugins that enable all sorts of shiny fancy features without much work. One of the very usefull ones that I find myself using on all kinds of projects is tablesorter- that makes clientside table sorting almost free.

Working in the Microsoft domain I have of course also been working with Microsofts ASP.NET Ajax Librarywhich also brings quite a few cool things to the table. Most basically it enriches the javascript experience by providing namespaces, intellisence and a bunch of extentions to the basic javascript type system. On top of that there are a lot of extenders to work with accordions, watermarks, listsearch etc. were most projects will find something that is useful to provide a better UI experience. The latest addition, that I am already very fond of even though it is still just in the beta version is templates. This gives us a easy way to do databinding on the client - one-way/two-way livebindings, and ways to do this both declaratively and imperatively. In other words it provides a rich templating experience and no more clumbsy string manipulation!

Next thing that is important when working with Ajax is having some solid libraries to do JSon serialization. Here I will strongly recommend JSON2for the client because eval is evil. Also a small but important thing to know is that data must be serialized and provided as a string when using JQuery to call a WCF service. On the serverside, I recommend Json.NET or maybe Json for the compact framework if you need something that is easier and more extendable than the .NET build in DataContractSerializer.

Finally something that might also be worth looking at to get better performance is using a content delivery network to reference the different scripting librarys. Here I will recommend looking at either Microsoft Ajax Content Delivery Networkor Google AJAX Libraries. Both seem very reliable and will give what you need, so its mostly a matter of personal preference.

18okt04_ajax_logo_150_rgb

ajax_logo2

Tags: , ,

Javascript - weak on getting week

by DotNetNerd 23. December 2009 08:42

Well this is one of those posts that start out being as a reminder for myself, since I had to do a script that I don't want to waste my time having to write again later on. Basically I ran into a customer who wanted week numbers added to a calendar. This seemed basic enough, but apparently getting a weeknumber is not a native thing in javascript.

First I picked up a script to add a getWeek method to the Date prototype, and I was a happy man. Sadly not customer not quite as much. It turns out that we do not follow the ISO 8601 standard for defining weeknumbers here in Denmark. According to my projectmanager the rule of thumb is that the first thursday always falls in week 1. This made me add a little extention so I now have a getIsoWeek and a getWeek method on my Date objects and this is how it was done.

/**
* Get the ISO 8601 week date week number
*/
Date.prototype.getIsoWeek = function() {
    // Create a copy of this date object 
    var target = new Date(this.valueOf());

    // ISO week date weeks start on monday 
    // so correct the day number 
    var dayNr = (this.getDay() + 6) % 7;

    // Set the target to the thursday of this week so the 
    // target date is in the right year 
    target.setDate(target.getDate() - dayNr + 3);

    // ISO 8601 states that week 1 is the week 
    // with january 4th in it 
    var jan4 = new Date(target.getFullYear(), 0, 4);

    // Number of days between target date and january 4th 
    var dayDiff = (target - jan4) / 86400000;

    // Calculate week number: Week 1 (january 4th) plus the  
    // number of weeks between target date and january 4th  
    var weekNr = 1 + Math.ceil(dayDiff / 7);

    return weekNr;
}

/**
* Get danish weeknumber.
* According to danish weeknumbers the first thursday always falls in week 1
*/
Date.prototype.getWeek = function() {
    var weekNr = this.getIsoWeek();

    var firstThursday = new Date(this.getFullYear(), 0, 1)
    while (firstThursday.getDay() != 4) firstThursday.setDate(firstThursday.getDate() + 1);

    if (firstThursday.getIsoWeek() == 2) weekNr--;

    if (weekNr == 0) weekNr = 1;

    return weekNr;
}

Tags:

Ajax Minifier - come and get your low hanging fruit

by DotNetNerd 21. December 2009 16:43

Not too long ago Microsoft released the Ajax Minifier, which can be downloaded from codeplex. It's basically just another javascript minifier, but the good thing about is it that the download includes both a commandline tool, an MS Build task and an assembly, so you can do your minification any way you like. Either way you wait to use it is very simple and it is explainted in the chm file which is included in the installation.

Today I finally got around to using it, for a HttpHandler that I wrote to serve some javascripts that I wanted to aggregate into one file and have them minified. It really took no time at all, and reduced my site from needing 13 files to 1 that was reduced in size by a little over 30%. All it required was about 10 lines of code in the HttpHandler (including handling caching). So basically what I am saying is that there is no excuse not to get this performance boost, since it is really low hanging fruit ripe for the plucking.

 

Tags:

Flickr og billedwidgets

by DotNetNerd 29. December 2008 11:29

En af mine gamle lidenskaber der indimellem popper frem er at lege med billeder, og nu jeg har haft ferie gav det sig udslag i at jeg ville prøve at lave en billedvæg til mit site, hvor billederne skulle trækkes fra flickr. Jeg havde egentlig forventet lidt bøvl, men selve det at trække billeder kræver ikke andet end følgende.

Flickr flickr = new Flickr("apiKey", "sharedSecret");
PhotoSearchOptions options = new PhotoSearchOptions();
options.Tags = "Christian";
options.Extras |= PhotoSearchExtras.DateTaken | PhotoSearchExtras.OriginalFormat;
options.UserId = flickr.PeopleFindByEmail("[email protected]").UserId;
options.TagMode = TagMode.AnyTag;
options.SortOrder = PhotoSearchSortOrder.DateTakenDesc;
options.PerPage = 6;
Photos photos = flickr.PhotosSearch(options);

Photos indeholder så en PhotoCollection som hver har urls til billederne i original, medium, lille og thumbnail størrelse.

Herfra manglede jeg så bare en eller anden smart måde at vise billederne på. Jeg faldt hurtigt over FancyBox, som er en JQuery plugin der også er rigtigt nem at bruge, og lader brugere trykke på en thumbnail og se hele billedet. Dagen efter poppede der tilfældigvis en blogpost ind omkring TinySlideShow, som lige som navnet antyder giver mulighed for at lave et slideshow. Det skulle naturligvis også prøves af, og da jeg i noget tid gerne have ville finde på noget nyt til hovedsiden på dotnetnerd.dk var det jo oplagt.

 

JQuery nu en del af .NET pakken!

by DotNetNerd 28. September 2008 20:29

Jeg er selv en af de mange der har forelsket mig i JQuery, da det er et fantastisk værktøj der gør livet meget lettere for webudviklere. Dagens gode nyhed som kan læses fra Scott Gu her og fra Hanselman her er at Microsoft fra nu af shipper JQuery sammen med .NET og der vil blive lavet kommentarer til javascript intellisence til det :)

Who am I?

My name is Christian Holm Diget, and I work as an independent consultant, in Denmark, where I write code, give advice on architecture and help with training. On the side I get to do a bit of speaking and help with miscellaneous community events.

Some of my primary focus areas are code quality, programming languages and using new technologies to provide value.

Microsoft Certified Professional Developer

Microsoft Most Valuable Professional

Month List

bedava tv izle