Tyson Lloyd Cadenhead – User Interface Developer

July 14, 2011

Skinny ControllerI’ve recently been thinking about what it would mean to emulate the MVC best practice of skinny controllers that started in the confines of server-side development within the much more glamorous language and beautiful JavaScript. For those of you who haven’t read some of my previous posts, I am a huge advocate of using Model View Controller architecture in client-side code as well as on the server-side. I’ve written in depth about what MVC looks like on the client-side, so I won’t bother to delve into that explanation here.

The basic idea of skinny controllers is that the models in the MVC architecture should really do more heavy lifting than they traditionally handel because the models are more reusable than the controllers, which should really be serving their proper role of directing traffic, or in the case of client-side controllers, listening for events and responding to them.

Following the fat model, skinny controller mantra to its logical place in client-side code, the places where the model should do the heavy lifting are:

  • Validation in the case of CRUD functionality and post methods.
  • Type-conversions and data manipulation.
  • Storing data in memory or in HTML5 databases to minimize server hits.

The benefit of all of these being in the model layer rather than the controller layer, or worse yet, in the views, is that multiple events in the controller can easily tap into the same functionality, which cuts down on duplicate code and lowers the risk of making variations in type-conversion or validation.

For example, if a view is hitting a JSON datasource to get information about a user, the JSON might look something like this:

{
   'id': 1112,
   'firstname': 'Darth',
   'lastname': 'Vader',
   'birthday': 1256953732
}

and our JavaScript model, which uses jQuery to make Ajax calls, might look something like this:

myApp.Model.User = {

    /**
    * @function
    * @param {Object} params
    * @param {Function} success
    * @param {Function} error
    */
    find: function(params, success, error) {

        // This assumes that you are using a getter / setter to save data to memory
        if (myApp.get('user_' + data.id)) {
            success(myApp.get('user_' + data.id));

        // Get the data via Ajax if it's not in memory
        } else {

            $.ajax({
                url: '/myapp/user/get',
                data: params,
                dataType: 'json',
                type: 'get',
                success: function(data) {

                    // Here, we do a little data manipulation so that
                    // we don't have to do this in the controller or the view

                    data.name = data.firstname + ' ' + data.lastname;
                    data.birthday = new Date(data.birthday);

                    // Use some type of getter / setter to save the data to memory
                    myApp.set('user_' + data.id, data);

                    // Fire off the success function after the data manipulation
                    success(data);

                },
                error: error
            });

        }
    }

};

The model above is much larger than it could be, but all of the type-conversion and storing to local memory are now happening at the data level where it should be rather than being misplaced in the controller or the view.

I have to admit, I’ve only been thinking this direction for a few days when it comes to the client-side, but it has radically changed my viewpoint on what I think the model should actually be doing in an Ajax application.

May 30, 2011

A few weeks ago, I started using SASS. What is SASS? It’s an acrostic that stands for “Syntactically Awesome Style Sheets.” SASS is run from the command line and essentially lets you write stylesheets with things like variables, nesting and mixins (which are pretty much the equivalent of the functions in a real programming language).

If you’re like me and you’ve spent a lot of time writing CSS, you probably find yourself making a lot of style declarations that are basically the same with only some minor variassions. In the past, the only way to really make CSS maintainable was to give DOM elements a long list of classes like:


<div class="yellow-background
round-corner-5px-radius large-text">
   This is large text on a yellow background
   with rounded corners and a 5px radius!
</div>

Of course, the problem with that is if you needed to make a change, say you needed to remove the 5 pixel radius on the example above, you would need to make the change to the HTML, not the CSS. Obviously, that model is not the best, because you want to be able to style with CSS, not with HTML, right?

The answer that SASS provides is that styles can inherit other styles. That way, you can make a style declaration once and have multiple classes and ids inherit it.

SASS style is compiled down to CSS, but you never have to touch the actual CSS files again, making it easier to maintain.

If you haven’t given SASS a shot yet, I would urge you to download it and see how much easier it makes the styling process.

Anyway, the point I’ve been working my way to is that with all the cool new things that CSS3 has brought us like rounded corners, gradients and shadows, the problem is that different browsers expect them to be presented differently.

For example, in the case of rounded corners, Google Chrome and Safari both look for

-webkit-border-radius: 5px 5px 5px 5px;

while Firefox, up until Firefox 4 looked for

-moz-border-radius: 5px 5px 5px 5px;

and Firefox 4 and IE10 along with every browser in the future will simply look for

border-radius: 5px 5px 5px 5px;

This can create a huge mess in your stylesheets if you have a lot of rounded corners and eventually, you’ll probably want to take out the Mozilla and Webkit specific declarations once they start supporting the non-specific declaration.

With SASS, you can make a single mixin that will handle any rounded corner like this:

@mixin rounded($top: 5px, $left: 5px, $bottom: 5px, $right: 5px) {
   border-radius: $top $left $bottom $right;
   -moz-border-radius: $top $left $bottom $right;
   -webkit-border-radius: $top $left $bottom $right;
}

The above example lets you pass in four variables for the top, left, bottom and right border radius. If you don’t pass anything in, it assumes each one is 5px. When you need to have a rounded corner now, all you have to do is:

.myClass { @include rounded; }

Or if you want to have a 10 pixel radius:

.myClass { @include rounded(10px, 10px, 10px, 10px); }

The same principle applied to a drop shadow would look like this:

@mixin shadow($type: inset, $top: 0, $left: 0, $blur: 1px, $color: #FFFFFF) {
   box-shadow: $type $top $left $blur $color;
   -moz-box-shadow: $type $top $left $blur $color;
   -webkit-box-shadow: $type $top $left $blur $color;
}

Gradients are a little more complicated and your mixin for a gradients really depends on your needs. Here is what I’ve been using to handle a gradient with either two stops or three stops. It uses an if statement to determine whether a third stop has been provided.

@mixin gradient($first, $second, $third: false) {
  background: $second;
  @if $third {
   filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$first', endColorstr='$second');
   background: -webkit-gradient(linear, 0% 0, 0% 100%, from($first), color-stop(0.5, $second), to($third));
   background: -moz-linear-gradient(linear, 0% 0, 0% 100%,  $first,  $second, $third);
  }
  @else {
   filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='$first', endColorstr='$second');
   background: -webkit-gradient(linear, left top, left bottom, from($first), to($second));
   background: -moz-linear-gradient(top,  $first,  $second);
  }
}

Using the mixin above is as easy as this:

.myClass { @include gradient(#cccccc, #dddddd, #cccccc) }

Of course, the example above doesn’t provide for every possible senario with the CSS3 gradient, but it served the needs for the project I was working on at the time.

As you can see, SASS can be a real life-saver as stylesheets get more and more complex and the need for browser-specific declarations becomes more of a reality in the ever-changing world of web development.

April 24, 2011

We now have HTML5 and CSS3.

Browsers are still racing to actually implement them, but the specs are here, whether they are fully realized in the wonderful world of browsers or not. So the real question becomes, what should we do with the knowledge we have of things to come?

What I am going to advocate is that we should start using as much HTML5 markup as we can get away with now, because if we do, we’ll be a step ahead of everyone else when people start scrambling to implement things that will become standard practice in the next few years.

For example, in the past if you were going to have an email address input field inside of a form, you would write something like this:

<input type="text" name="email" />

But in the HTML5 specs, we have a new input type called “email” that looks like this:

<input type="email" name="email" />

On most desktop browsers, the difference between the input type of “text” and the input type of “email” is non-existant.

However, we don’t know what UI browsers might implement in the future to make entering an email address easier. Apple is already using the alternate input type on the iPhone and the iPad to provide the user with an alternate keyboard layout that is more optimized for entering an email address. The “email” type won’t break older browsers that don’t support it, they will just treat it like a standard “text” input field.

My feeling is, why would you not use the “email” input type for emails?

There are a lot of examples like that where we can use future enhancement to prepare for whatever the future might hold without breaking the internet for users with older browsers. We can also use browser detection and provide JavaScript alternatives for things like the input field’s placeholder attribute even for the old browsers that don’t support it natively.

The point here is that HTML5 is coming and in some respects HTML5 is already here. We can either keep writing the same markup that our parents wrote, or we can prepare for the future by writing the markup our children will be proud of.

April 9, 2011

Has anyone ever told you that your application is too slow? What can you do about it? You can always point the finger at the server-side people and mumble something about the database being the problem, but is there anything you can do to speed up the loading time? Can you speed up the browser’s reaction to user-activated events?

Here are a few things I’ve observed that can seriously improve application performance.

Minify and combine your code
This should be a no-brainer. It takes longer to load multiple files than it does to load a single file because we are making fewer http requests. Minifying your code removes unnecessary spaces and line breaks and removes comments. All of those things are essential for the developer, but not essential for the user.

Keep the DOM light
True story. I was working on a Sencha Touch project that was in its final stages. The performance was decent in a computer browser, but when it was run as an app on an iPhone, after the user hit about 5 screens, the app would just stop responding. I went back and made sure that every time the user left a screen, that screen view was removed from the DOM. The results were amazing!

The truth is that if your application has clean separation of business logic and display code, it shouldn’t be too hard to continually remove views from the DOM without losing important information. If you can’t do that, you are relying too much on the DOM to do things that it was never intended to do. A good rule of thumb is to always remove anything that isn’t currently being displayed.

Minimize calls to the server
Every time you hit the server for data, your application has to wait to retrieve it. If you can get all the data you need in one Ajax call, don’t waste your users time making two calls.

Once you get data, if it is appropriate, have your application remember it. That way, it doesn’t have to ask for it again during the same session. Of course, that won’t work if you need to retrieve live data, but otherwise, it makes sense.

CSS3 is cool… but don’t overdo it
This is especially applicable to the CSS that relies on transparencies. Depending on the browser, things like drop shadow and opacity can slow things down considerably.

Animations that rely on these can be costly too. I wouldn’t say to totally avoid them, but be mindful of the blow that these cool effects have to performance.

Follow the rules
JavaScript is a very flexible language, but some choices are better than others. There are sites out there outlining things not to do with JavaScript, so read up on them and avoid bad choices like using the eval() function or creating functions inside of a loop. You can do better than that!

This just skims the surface, but I hope that it helps to start thinking in the direction of writing JavaScript for speed. Your users will appreciate it!

April 1, 2011

Several months ago I wrote about event binding using ExtJS or Sencha touch. Something that you may or may not know is that you can achieve the same thing with jQuery using custom even binding.

In case you didn’t see my Sencha post about this, or if you don’t work with Sencha, let me tell you what I mean by event binding. Event binding can be used to loosely couple actions so they never break. Essentially, you broadcast to your entire application “Hey! I have something to say! Does anybody want to hear it?” Your modules can either say “Hey, I’d like to hear what you have to say” or else, they can just ignore it. Either way, nothing breaks. You can even have several modules respond to the same event in different ways.

So, on to the code… Make sure that you are using an up to date version of the jQuery library. At some point back in time, this didn’t work yet.

To create a custom event with jQuery, you can use the “trigger” function like this:


   $(document).trigger('my-custom-event', ['hi!  I am a custom variable!']);

You can actually bind a custom event to any DOM element, but for the sake of making it available to your entire application, the document object is usually a pretty safe choice. As you can see, we are also passing a variable.

Now you just need to have a listener at any place in your code that is executed before the trigger event, like this:


   $(document).bind('my-custom-event', function(v) {
      alert(v);
   });

So your code ends up looking something like this:


   $(document).bind('my-custom-event', function(v1, v2) {
      alert(v1);
   });

   $(document).bind('my-custom-event', function(v1, v2) {
      alert('firing ' + v2);
   });

   $(document).trigger('my-custom-event',  [
      'Hi!  I am a custom variable!',
      'Hi! I'm a different custom variable!'
    ]);

You should now see two separate alerts fired from the same trigger. Now all you have to do is bind custom events to your individual modules and they will never touch again. Feel powerful yet?

Portfolio

See More