Tag Archives: jQuery - Page 2

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:

Updating the jQuery vsdoc File in Your ASP.NET Web Projects

Intellisense in jQuery is a treat. But what happens when you start a fresh web project and want to replace jQuery 1.4.0 (out of the box – VS project template) with the latest version? You go to jQuery.com and get the latest jQuery files. But what about the vsdoc file which gives that sweet intellisense?

This is how I do it (when I can’t use Nuget, for one reason or another):

  1. Navigate to Microsoft’s page which has links to its CDN files.
  2. Click the link jQuery Releases on the CDN where you will see text urls to the latest versions of jQuery, as made available on the CDN.
  3. Copy and paste the relevant vsdoc file url into the address bar of you browser (I use Firefox). That loads the javascipt file.
  4. Save the file to your system, ready to be added to your Visual Studion Web Projects.

Or, you could just use Nuget…

Default Values and Settings

A really cool use of the jquery extend function is to implement default values in an object. One of the features of extend is that when it merges 2 objects, the properties of the new object, which have the same name as properties in the existing object, will supercede the properties of the existing object. This can be utilised to implement default values.

Lets say we have a business object which has a property Settings. And the Settings property has a number of properties. Now, we can pass in an object (lets call it options) which will have a set of properties. The idea being, the options object will be an object that the caller can configure to set the settings of our business object i.e. we will give the calling code the ability to set the Settings for the business object. The following code shows how we can do that. The commenting in the code explains what is going on:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>

    <script src="jquery-1.7.1.js" type="text/javascript"></script>
    <script type="text/javascript">

        //  This is the constructor function for our business object. It takes a parameter
        //  called options in to enable the calling code to set option values.
        function myBusinessObject (options) {

            var Settings = {
                closeWhenDone: true,
                color: 'blue',
                animation: 'slide'
            };

            //  Assign Settings to the prototype for the object, to create
            //  default values when the object is first created.
            this.prototype = Settings;

            // Use extend to override default Settings with options passed in.
            // Only those properties which have the same name will be superceded.
            $.extend(Settings, options);

            // This method is just to view the settings, for the purposes of this example.
            this.getSettings = function() {
                return Settings;
            };
        };

        function createObjectAndSeeSettings() {
            //  create a new business object, passing in an options object.
            //  Note that no value for animation is passed in. The default remains.
            var newObject = new myBusinessObject({ closeWhenDone: false, color: 'red' });
            var settings = newObject.getSettings();
            return settings.closeWhenDone + " " + settings.color + " " + settings.animation;
        }

    </script>

</head>
<body>
    <input id="ShowSettingsButton" type="button" value="Show Settings" onclick="alert(createObjectAndSeeSettings());" />

</body>
</html>

Note how the object being passed in does not include a property for animation. That being the case, the default value “slide” remains.

$.extend and Inheritance

I have written about how to implement inheritance in javascript in a couple of previous posts here, here and here. Today, I am going to look at one way which you can implement inheritance with jQuery.

There’s a jQuery method called extend. This method serves a wider purpose i.e. to Merge the contents of two or more objects together into the first object. However, you can use it to implement a certain kind of inheritance pattern. That is, one whereby the properties of one object are copied to another, augmenting that second object. Lets look at some code!

Similar to my previous examples, we will create a parent object called person and inherit from it using our “property copying” pattern:

        // using the object literal notation, create a person object
        var person = {
            legs: 2,
            arms: 2,
            getName: function() {
                return this.name;
            }
        }
			
        // Create an empty object, and add some properties to it. 
        // This will be the additional properties of the inheriting type.	
		var newBits = { };
		newBits.age = 37; 
		newBits.name = 'Dave';
        newBits.showAge = function() {
            return this.age;
        }

        // Create and pass into extend an empty object so as to preserve the state of the "person" object.
        // The "dave" object now contains all the properties of the parent (person) and the new properties in newBits.
		var dave = { };
		$.extend(dave, person, newBits); 

        function ShowAgeIfPresent(personLikeObject) {
            if (personLikeObject.age === undefined) {
                return 'Person has no age';
            }
            else {
                return personLikeObject.showAge();
            }
        }

Note that this is definitely a different inheritance pattern to the previous ones I have blogged about. For example, where a method is copied from the person object, every instance of the inheriting object will have its own copy of that method. Whereas, in the previous patterns, the method was stored once, in the prototype object, which every inheriting object would use.

So far, my favourite is the still new Object.create method. But this $.extend method is an interesting approach.

Here is the download code for this post.