Blog Archives

The Prototype Pattern – Techniques, Strategies and Patterns for Structuring JavaScript Code

Using the JavaScript Prototype Pattern

This is the 2nd post in a series on techniques, strategies and patterns for writing JavaScript code. In my previous post I introduced what I call “function spaghetti code” and explained some of the problems it introduces. I also talked about the impact of global variables and how closures add a much needed solution. In this post I’ll introduce the Prototype Pattern and show how it relies on built-in functionality in the JavaScript language.

I’ve worked through some of the patterns I’m covering in this series with my good friend John Papa over Skype and we’ve talked about pros and cons of different approaches. For example, he initially recommended defining multiple variables using a single var based on JSLint suggestions (that was covered in the previous post) and I agreed that it was a better approach than using var for every variable. It’s interesting how code evolves with feedback from multiple people. John and I have definitely come to enjoy working with a few different patterns and although the Prototype Pattern isn’t in my favorites list, I’ve always felt that it’s good to understand and know the different options out there. That’s why I decided to include it in this series.

The Prototype Pattern can be broken out into two main sections including a constructor section and a prototype section. Prototyping allows functions and properties to be associated with objects. However, instead of each object instance getting a copy of all functions/properties each time an object is created, only one set of functions/properties exists across all objects resulting in less memory consumption. In other words, functions and properties are defined once per prototype rather than once per object.

As a quick review, I showed the following code in a previous post. The code simply lists all functions directly with no encapsulation and defines several global variables. While the code works fine this way, I’ll examine how we can restructure it to follow the Prototype Pattern.

window.onload = function () {
    eqCtl = document.getElementById('eq');
    currNumberCtl = document.getElementById('currNumber');
};

var eqCtl,
    currNumberCtl,
    operator,
    operatorSet = false,
    equalsPressed = false,
    lastNumber = null;

function add(x,y) {
    return x + y;
}

function subtract(x, y) {
    return x - y;
}

function multiply(x, y) {
    return x * y;
}

function divide(x, y) {
    if (y == 0) {
        alert("Can't divide by 0");
        return 0;
    }
    return x / y;
}

function setVal(val) {
    currNumberCtl.innerHTML = val;
}

function setEquation(val) {
    eqCtl.innerHTML = val;
}

function clearNumbers() {
    lastNumber = null;
    equalsPressed = operatorSet = false;
    setVal('0');
    setEquation('');
}

function setOperator(newOperator) {
    if (newOperator == '=') {
        equalsPressed = true;
        calculate();
        setEquation('');
        return;
    }

    //Handle case where = was pressed
    //followed by an operator (+, -, *, /)
    if (!equalsPressed) calculate();
    equalsPressed = false;
    operator = newOperator;
    operatorSet = true;
    lastNumber = parseFloat(currNumberCtl.innerHTML);
    var eqText = (eqCtl.innerHTML == '') ?
        lastNumber + ' ' + operator + ' ' :
        eqCtl.innerHTML + ' ' + operator + ' ';
    setEquation(eqText);
}

function numberClick(e) {
    var button = (e.target) ? e.target : e.srcElement;
    if (operatorSet == true || currNumberCtl.innerHTML == '0') {
        setVal('');
        operatorSet = false;
    }
    setVal(currNumberCtl.innerHTML + button.innerHTML);
    setEquation(eqCtl.innerHTML + button.innerHTML);
}

function calculate() {
    if (!operator || lastNumber == null) return;
    var currNumber = parseFloat(currNumberCtl.innerHTML),
        newVal = 0;
    //eval() would've made this a whole lot simpler
    //but didn't want to use it in favor of a more
    //"robust" set of methods to demo patterns
    switch (operator) {
        case '+':
            newVal = add(lastNumber, currNumber);
            break;
        case '-':
            newVal = subtract(lastNumber, currNumber);
            break;
        case '*':
            newVal = multiply(lastNumber, currNumber);
            break;
        case '/':
            newVal = divide(lastNumber, currNumber);
            break;
    }
    setVal(newVal);
    lastNumber = newVal;
}

 

To start using the Prototype Pattern you need to first create a constructor as shown next. The constructor can accept one or more parameters and define any variables that the object needs. Note that the variables are scoped to the object rather than to the global scope.

var Calculator = function (tb, eq) {
    this.eqCtl = document.getElementById(eq);
    this.currNumberCtl = document.getElementById(tb);
    this.operator = null;
    this.operatorSet = false;
    this.equalsPressed = false;
    this.lastNumber = null;
};


Once the constructor is defined a prototype can be created using the prototype keyword. Although you can create a prototype for each function, it’s more convenient (and less typing) to take advantage of JSON-style syntax where the function name represents the JSON property name and the value represents the function. An example of defining two functions in a prototype is shown next. Notice that each function is separated with a comma just as you would separate properties defined in a normal JSON object. It’s officially called a JavaScript object literal, but if you’re familiar with JSON it uses the same standard syntax (thanks to Craig Stuntz for clarifying that):

Calculator.prototype = {

    add: function (x, y) {
        return x + y;
    },

    subtract: function (x, y) {
        return x - y;
    }
}


The original function-based calculator code shown earlier can be refactored to follow the Prototype Pattern as shown shown next. A prototype is created for the Calculator object and functions/properties are defined within the prototype using JavaScript object literal syntax.

Calculator.prototype = {

    add: function (x, y) {
        return x + y;
    },

    subtract: function (x, y) {
        return x - y;
    },

    multiply: function (x, y) {
        return x * y;
    },

    divide: function (x, y) {
        if (y == 0) {
            alert("Can't divide by 0");
        }
        return x / y;
    },

    setVal: function(val) {
        this.currNumberCtl.innerHTML = val;
    },

    setEquation: function (val) {
        this.eqCtl.innerHTML = val;
    },

    clearNumbers: function () {
        this.lastNumber = null;
        this.equalsPressed = this.operatorSet = false;
        this.setVal('0');
        this.setEquation('');
    },

    setOperator: function (newOperator) {
        if (newOperator == '=') {
            this.equalsPressed = true;
            this.calculate();
            this.setEquation('');
            return;
        }

        //Handle case where = was pressed
        //followed by an operator (+, -, *, /)
        if (!this.equalsPressed) this.calculate();
        this.equalsPressed = false;
        this.operator = newOperator;
        this.operatorSet = true;
        this.lastNumber = parseFloat(this.currNumberCtl.innerHTML);
        var eqText = (this.eqCtl.innerHTML == '') ?
            this.lastNumber + ' ' + this.operator + ' ' :
            this.eqCtl.innerHTML + ' ' + this.operator + ' ';
        this.setEquation(eqText);
    },

    numberClick: function () {
        var button = (event.target) ? event.target : event.srcElement;
        if (this.operatorSet == true || this.currNumberCtl.innerHTML == '0') {
            this.setVal('');
            this.operatorSet = false;
        }
        this.setVal(this.currNumberCtl.innerHTML + button.innerHTML);
        this.setEquation(this.eqCtl.innerHTML + button.innerHTML);
    },

    calculate: function () {
        if (!this.operator || this.lastNumber == null) return;
        var displayedNumber = parseFloat(this.currNumberCtl.innerHTML)
            newVal = 0;
        //eval() would've made this a whole lot simpler
        //but didn't want to use it in favor of a more
        //"robust" set of methods to demo patterns
        switch (this.operator) {
            case '+':
                newVal = this.add(this.lastNumber, displayedNumber);
                break;
            case '-':
                newVal = this.subtract(this.lastNumber, displayedNumber);
                break;
            case '*':
                newVal = this.multiply(this.lastNumber, displayedNumber);
                break;
            case '/':
                newVal = this.divide(this.lastNumber, displayedNumber);
                break;
        }
        this.setVal(newVal);
        this.lastNumber = newVal;
    }
};


To use the Calculator object, create a new instance and pass the names of the HTML container objects into the constructor (the container objects identify the IDs of controls used to display calculations – see the HTML code below):

var calc = null;
window.onload = function () {
    calc = new Calculator('currNumber', 'eq');
};


The HTML used to render the calculator can reference the calc object created when the page loads. The following code demonstrates how this can be done to handle events as different div elements are clicked. I normally prefer to wire-up events to event handlers using jQuery in “real-world” applications to keep the HTML clean but wanted to focus on JavaScript patterns and avoid introducing additional libraries for this post. I’m not a big fan of defining onclick and other event handlers directly on HTML elements but let it slide for this post.

<div class="Calculator">
    <div class="CalculatorHead">
        <div id="eq" class="Equation"></div>
        <div id="currNumber" class="CurrentNumber">0</div>
    </div>
    <div>
        <div class="Button" onclick="calc.numberClick(event);">7</div>
        <div class="Button" onclick="calc.numberClick(event);">8</div>
        <div class="Button" onclick="calc.numberClick(event);">9</div>
        <div class="Button" onclick="calc.setOperator('/');">/</div>
        <div class="Button rowspan2" onclick="calc.clearNumbers();">C</div>
    </div>
    <div>
        <div class="Button" onclick="calc.numberClick(event);">4</div>
        <div class="Button" onclick="calc.numberClick(event);">5</div>
        <div class="Button" onclick="calc.numberClick(event);">6</div>
        <div class="Button" onclick="calc.setOperator('*');">*</div>
    </div>
    <div>
        <div class="Button" onclick="calc.numberClick(event);">1</div>
        <div class="Button" onclick="calc.numberClick(event);">2</div>
        <div class="Button" onclick="calc.numberClick(event);">3</div>
        <div class="Button" onclick="calc.setOperator('-')">-</div>
        <div class="Button rowspan2" onclick="calc.setOperator('=');">=</div>
    </div>
    <div>
        <div class="Button colspan2" onclick="calc.numberClick(event);">0</div>
        <div class="Button" onclick="calc.numberClick();">.</div>
        <div class="Button" onclick="calc.setOperator('+');">+</div>
    </div>
</div>

 

The Prototype Pattern provides a nice way to structure JavaScript code but there are several other roads you can travel if desired. In this next post I’ll talk about the Revealing Module Pattern and explain how it can be used.

Demos of all the patterns covered in this series can be downloaded below.

Download Code

To XML and Back: Using JSON in Android

JavaScript Object Notation (JSON) is competing with XML as the data encoding format of choice.

Video: Getting Started with ASP.NET MVC 1.0

I had the opportunity to speak at the Best of Mix 09 Phoenix event with Tim Heuer and Rob Bagby and had a lot of fun hanging out with everyone.  I was the last talk and due to time constraints didn’t get a chance to cover everything I had hoped to cover, but all of the important topics were discussed. 

The projection screen doesn’t show up too well in the video unfortunately, but all of the slides and sample code can be downloaded here for those that may be interested in following along. The talk covers the fundamentals of ASP.NET MVC, discusses some great features the framework offers and describes how jQuery and even Silverlight can be integrated.  The downloadable code samples demonstrate all of the features discussed in the video.

Getting Started with ASP.NET MVC 1.0 

Click here to view in Windows Media Player (right-click and you can save the file)

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

Emulating the UpdatePanel in ASP.NET MVC 1.0 with AjaxHelper

I just finished up a client application based on ASP.NET MVC 1.0 and thought I’d blog about some of the things I really liked.  If you didn’t catch my earlier post titled 5 Reasons You Should Take a Closer Look at ASP.NET MVC and are interested in learning more about what the MVC framework offers I’d recommend reading that first.  The client application my company built required a lot of AJAX functionality behind the scenes and I used jQuery along with MVC controller actions to pass JSON data back and forth in many cases.  However, I did take the UpdatePanel type approach in a few cases since it’s quite easy to do and very efficient as far as the data that gets passed back and forth between the client and server.

ASP.NET MVC 1.0 provides an AjaxHelper class that exposes a BeginForm() method.  HTML controls wrapped in the BeginForm() area are automatically AJAX enabled much like the ASP.NET UpdatePanel.  However, because ASP.NET MVC doesn’t use ViewState or ControlState at all, the calls back to the server are much more efficient when compared to the UpdatePanel (you can use a tool such as Fiddler to verify this:  www.fiddlertool.com).  Here are the basic steps to AJAX-enable sections of a view in ASP.NET MVC.

1. Add Ajax.BeginForm into your View

<% using (Ajax.BeginForm("EditCustomerProfile", null,
   new AjaxOptions { UpdateTargetId = "CustomerForm", OnSuccess = "onEditCustomerProfileSuccess" },
   new { id = "EditCustomerProfileForm" }))
   {
%>

<% } %>


BeginForm() has 11 different overloads that can be used.  This example creates an AJAX-enabled section using the AjaxHelper’s BeingForm() method and defines that a controller action named EditCustomerProfile will be called to retrieve the data.  Any route data that needs to be passed can be specified in the second parameter.  The third parameter represents the AjaxOptions that will be used as the client and server interact.  In this case I specify that a control with an ID of CustomerForm will be updated with the data returned from the server.  I also call a JavaScript success callback named onEditCustomerProfileSuccess to perform other necessary actions in the application if the AJAX call returns successfully:

function onEditOfficeProfileSuccess(content)
{
    if ($('#OfficeProfileValSummary').length == 0) //No validation control found so OK
    {
        ClearOfficeProfileControls();
    }
    GetOfficeProfiles();
}

The final parameter represents properties that are added to the form tag generated by BeginForm().  I simply assign the id of the form tag to EditCustomerProfileForm which is done to make it easier to filter controls using jQuery selectors elsewhere in the application.

2. Add the UpdateTargetID div

Once BeginForm() is defined you need to specify the object (div, span or other object) that will receive updates from the server as AJAX calls are made.  In my case I want an end user to complete a form, submit it to the server, validate it, perform business rules there, etc. and then return the form back to the client with a status message about the action.  The form is defined in a user control which is embedded within my ASP.NET MVC view using the HtmlHelper’s RenderPartial() method.  Since the form area gets updated after the call I wrap it with a div that has an ID of CustomerForm (the UpdateTargetID shown above).  Here’s the completed code:

<% using (Ajax.BeginForm("EditCustomerProfile", null,
   new AjaxOptions { UpdateTargetId = "CustomerForm", OnSuccess = "onEditCustomerProfileSuccess" },
   new { id = "EditCustomerProfileForm" }))
   {
%>
    <div id="CustomerForm">
        <% Html.RenderPartial("EditCustomerForm",Model.CustomerViewModel); %>
    </div>
<% } %>


When user submits the form and data returns from the server the CustomerForm div will automatically be updated without having to write any JavaScript code….just like the ASP.NET Web Forms UpdatePanel. The code for the controller action named EditCustomerProfile is shown next.  If everything validates properly it returns the EditCustomerForm user control with a message letting the client know that everything worked.  If errors are found they are added into the model’s error collection and displayed in the form.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditCustomerProfile(Customer customer, string email)
{
    string emailMessage = null;
    try
    {
        //#### Handle Email
        if (!String.IsNullOrEmpty(email) && Regex.IsMatch(email, @"^w+@[a-zA-Z_]+?.[a-zA-Z]{2,3}$"))
        {
            emailMessage = UpdateEmailAddress(email);
        }
        else //Email address is null or doesn't follow the RegEx pattern
        {
            emailMessage = "Please check that you entered your email address properly.";
        }

        //#### Handle updating Customer object data
        if (emailMessage == null && customer.IsCustomerValid)
        {
            OperationStatus opStatus = _CustomerRepository.Update(customer,
                c => c.CustomerID == customer.CustomerID);
            if (opStatus.Status)
            {
                ViewData["Status"] = "true";
                return View("EditCustomerForm",
                    new CustomerViewModel(_CustomerRepository.Get(c => c.CustomerID == customer.CustomerID),
                        "Navy", "Your profile information was saved."));
            }
        }
    }
    catch (Exception exp)
    {
        Logger.Log("Error in AccountController.EditCustomerProfile", exp);
    }
    ViewData["Status"] = "false";
    List<RuleViolation> violations = customer.GetRuleViolations().ToList();
    if (emailMessage != null) violations.Add(new RuleViolation("Email", emailMessage));
    ModelState.AddModelErrors(violations);
    return View("EditCustomerForm", new CustomerViewModel(_CustomerRepository.Get(c => c.CustomerID == customer.CustomerID),
        "Red", "There was a problem updating your profile."));
}

Adding UpdatePanel-like functionality into ASP.NET MVC applications is a snap and allows you to speed-up end user interaction with pages.  I personally like the fact that successful AJAX calls can easily be routed to callbacks without having to worry about wiring up any helper JavaScript objects.

 

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

Reflecting over JSON Data to Simplify Control Updates with jQuery

My company is currently working on a consulting project that uses ASP.NET MVC and a lot of jQuery and JSON behind the scenes for data transfer which is a lot of fun.  I’m personally tasked with the back-end processes but also handling user interface updates as JSON data is received.  I have a form with several different controls in it that are updated once JSON is returned from a controller action and the controls are updated using jQuery selectors.  Something like this:

$('#OfficeProfile_CustomerID').val(json.OfficeProfile.CustomerID);
$('#OfficeProfile_OfficeProfileID').val(json.OfficeProfile.OfficeProfileID);
$('#OfficeProfileAddress_AddressID').val(json.OfficeProfile.AddressID);
$('#OfficeProfile_OfficeTitle').val(json.OfficeProfile.OfficeTitle).convertNullToEmptyString();
$('#OfficeProfile_OfficeContactName').val(json.OfficeProfile.OfficeContactName).convertNullToEmptyString();
$('#OfficeProfile_NumberOfPeople').val(json.OfficeProfile.NumberOfPeople).convertNullToEmptyString();
$('#OfficeProfile_Phone').val(json.OfficeProfile.Phone).convertNullToEmptyString();
$('#OfficeProfile_Comments').val(json.OfficeProfile.Comments).convertNullToEmptyString();
$('#OfficeProfileAddress_Street').val(json.OfficeProfile.Address.Street).convertNullToEmptyString();
$('#OfficeProfileAddress_City').val(json.OfficeProfile.Address.City).convertNullToEmptyString();
$('#OfficeProfileAddress_StateID').val(json.OfficeProfile.Address.StateID).convertNullToEmptyString();
$('#OfficeProfileAddress_Zip').val(json.OfficeProfile.Address.Zip).convertNullToEmptyString();

While this code works fine, it quickly becomes a pain as JSON properties change and it’s just too much typing for my taste.  I decided that there must be a more compact way to do this given that there’s definitely a pattern to the ID names used in the jQuery selectors and the value assigned to each control.  After thinking about it more I realized that I need to use “reflection” (a technique used to inspect objects in the .NET framework) to access the JSON properties and then handle updates to the controls.  But, how do you reflect over a JSON object and figure out what properties it has?  Turns out it’s pretty easy…after a quick Google/Live search anyway.  You can iterate through the JSON object’s properties using a normal JavaScript for loop and then access each property name and value.  Here’s what I ended up doing to simplify the code above and make it more dynamic:

var prefix = '#OfficeProfile_';
var addrPrefix = '#OfficeProfileAddress_';
for (prop in json.OfficeProfile)
{
    var propVal = json.OfficeProfile[prop];
    if (prop == 'Address') //Object property within JSON..loop through Address object properties
    {
        for (addrProp in propVal)
        {
            $(addrPrefix + addrProp).val(propVal[addrProp]).convertNullToEmptyString();
        }
    }
    else
    {
        $(prefix + prop).val(propVal).convertNullToEmptyString();
    }
}

The json variable in the previous code represents the JSON returned from the call to the server and it exposes an OfficeProfile property.  The code loops look through each property in the OfficeProfile object, stores the value and then uses the property name to locate the appropriate control within the form that I want to update (using jQuery selector syntax).  I suspect there’s additional refactoring that I could apply but has worked out nicely so far.

 

Logo

For more information about onsite, online and video training, mentoring and consulting solutions for .NET, SharePoint or Silverlight please visit www.thewahlingroup.com/.

WP Like Button Plugin by Free WordPress Templates