Jun 21 2014

New Versions of Mvc Controls Toolkit and Data Moving Controls Suite

Category: Asp.net | Javascript | MVC | WebApiFrancesco @ 21:43

New 3.0.0 release of the Mvc Controls Toolkit. See the list of changes.

New 1.2 release of the Data Moving Controls Suite. See the list of changes.

 

Enjoy!

Francesco

Tags: , , ,

Dec 21 2013

JavaScript Intensive Web Applications 3: Enhancing Applications with Ajax

Category: JavascriptFrancesco @ 21:43

JavaScript Intensive Web Application 1: Getting JavaScript Intellisense

JavaScript Intensive Web Applications 2: Enhancing Html with JavaScript

paramsIntellisense1

What are the advantages and drawbacks of using Ajax to update web pages? How to decide if Ajax calls should return html or JSON? In this post I will give some answers to the above questions and I will give some tricks to enhance also the Html created dynamically as a consequence of Ajax calls with JQuery Plug-ins .

Most of people that uses Ajax when asked why they are using it, answer that Ajax calls improve performance and user experience….Well, for sure they improve user experience, but I don’t know if possible performance improvements might be relevant…Finding the right answer to all these questions is the first step toward an optimized use of Ajax based techniques.

What are the times that compose the the total response time of a server request? A network latency time is needed to establish the connection with the server, a trasmission time is needed to send all bytes (that depends on the available bandwidth), a server response time, and a browser re-drawing time. Now, if the server is well designed, and if we are not sending tons of html , the bottlenecks are the latency time and the browser re-drawing time. With all nowadays continuous technological improvements bandwidth will impact always less on performance. Also the browser re-draw time will impact always less on the performance. So the request response time will be always more and more tied to the network latency. Accordingly, redrawing the whole page or just a part of it would require almost the same communication time. Moreover re-drawing just a not negligible area of the page (say the 25% of the page) requires almost the same time as re-drawing the whole page since a whole page re-draw is more efficient than a partial re-draw.

As a conclusion in most of the cases Ajax techniques don’t imply any appreciable improvement in the total response time! So why using Ajax?

  1. If we need to refresh just a small part of the page, as in the case of  an auto-complete that write suggestions under the textbox we are writing in, there is a not negligible improvement of the response time.
  2. During the Ajax update the state of the remainder of the page is maintained. What does this mean? From the user experience point of view this means something like: the browser will not loose the scrolling we have done, and the textbox the user is writing in will not loose the focus…otherwise it would be impossible to have auto-complete and similar widgets working properly. One might object that we might restore the whole state also after a standard page redraw…Yes it is true…but before the page has been completely redrawn the user would see the page returning to the top of the document, the Textbox disappearing, and so on….and similar unacceptable stuffs.
    Maintaining the whole state is important also for more macroscopic state information. Let think ,for instance, to a grid with a detail view that retrieves row details from the server when a row is selected, and show them in a separate area of the page. A complete page refresh might cause the loss of the whole grid state, that is the data page shown, sorting and filtering, the possible scrolling of the grid body, etc. Now, in theory, it is possible to rebuild the whole state also after a whole page refresh but this might confuse the user that would see the grid disappearing, being re-drawn in a different position and then being scrolled till reaching the previous position. However, this isn’t the only drawback, if grid data are taken from a shared database (as it is usual..), also the same page with the same sorting and filtering might show different data disappointing completely the user. Moreover, any attempt to take into account all these state information on the server side might undermine the modularity of our application turning our Controllers into “spaghetti code”.

So when  is it convenient to use Ajax techniques?

Simple, either when we need to update just a small part of the page or when we need to keep the state of a part of the page. Also the reason for implementing our application as a Single Page Application, that is, an application that never leaves the same physical page, is always the same: keeping state information in the physical page. In the next post dedicated to Single Page Applications we will see also other reasons for keeping state information in the page but the fact remains that …the reason why Single Page Applications exist is… keeping state information in the page.

Now, when our pages become more an more complex keeping state information inside Html nodes may lead to “spaghetti code”, so in a way that is completely analogous to the Mvc pattern on the server side it is more and more convenient to store information inside a client side ViewModel, and then using that ViewModel to render adequate Html. On the server side we use Razor Views to turn models into Html, while on the client side we use client side templates to create dynamically Html from a JavaScript model…..Well, this is the main reason to use Ajax calls where client and server exchange JSON!

JSON based Ajax techniques will be discussed in greater detail in the next post of this series. Here it is worth to point out just when they should be preferred to standard Ajax techniques where the server returns immediately the needed html. Since JSON techniques conforms with the idea of using a client side ViewModel, that in turn ensures a better modularity, one might draw the conclusion that they should always be preferred to standard Html-returning Ajax techniques!….NO…false, JSON based techniques should be preferred only when you may use client side templates! Below the typical reasons that, in some circumnstances, prevent the use of client templates:

  1. Pages created with client templates are not visible to search engines.
  2. Some slow mobile device might not be able to render client templates with an acceptable performance.

You might object that also in case Ajax calls return Html, that Html is not visible to search engines. TRUE….but IRRELEVANT because, when we use Ajax calls returning Html, the initial page is not rendered with Ajax, because the same Action Method that serves an Ajax request may be called also when the initial page is rendered,…but without using Ajax and usingt @Html.Action(…), and @Html.RenderAction(…), instead. This way, the initial page is completely visible to search engines. Accordingly, if we make a clever use of Html-returning Ajax Mvc controllers we may produce web Applications that are completely visible to search engines. Here “clever use” means, for instance, that when we change the page of a grid we don’t do it with Ajax but with a link based pager (possibly...with a smart encoding of the page number in the URL). In other terms, we should use Ajax only for that operations that are not performed by search engines. So, for instance,  we may show a detail area in a grid page, but then the same detail page must be available also as a separate page either through a "pretty url", through a link.

 

Let see in detail, how we may avoid initial Ajax calls when we render the whole page with the simple example of the grid with a detail view.

Suppose we have a PlannerController with a ToDoList action method that fills a ViewModel with a paged list of ToDoItems, and a DisplayDetailToDo action method that fills a ViewModel with the details of a single ToDoItem. Suppose that we display the ViewModel  filled by the ToDoList action method in a ToDoList View containing a Grid and a detail area, and suppose that initially the detail are should contain the first item of the grid. Then the detail area of the ToDoList View should be something like:

  1. <div id="detailArea" data-update-url="@Url.Action("DisplayDetailToDo", "Planner")">
  2.     @Html.Action("DisplayDetailToDo", "Planner", new {ItemId=Model.Items[0].ItemId})
  3. </div>

Then, whenever the user select the ToDoItem with Id –> selectedId in the grid we perform the Ajax call:

  1. var ajaxRoot=$('#detailArea');
  2. ajaxRoot.load(ajaxRoot.attr("data-update-url")+"?ItemId="+selectedId );

That we may place in a click handler (my previous post shows how to add modularly click handlers) that catches all events bubbled by the rows of the grid. The grid side code depends on the chosen grid, but we may take selectedId from an Html5 attribute of the button, link or other Html node used to select the grid row.

In both cases we use the same action method that should be something like:

  1. public ActionResult DisplayDetailToDo(int ItemId)
  2. {
  3.     var model = repository.GetToDo(ItemId);
  4.     ...
  5.     ...
  6.     ...
  7.     return PartialView(model);
  8. }

Where I omitted all errors handling code.

Our problem now is how to enhance also the Html returned by the Ajax call with jQuery widgets. We may use the basically the same technique I have shown in my previous post, based on the widgetsHelpers.initialize method, since when we insert new Html with the jQuery .html method all JavaScript contained in the Html string is executed. However, the widgetsHelpers.initialize method contains the .ready jQuery method…that doesn’t work with dynamically added content. This problem is easily solved with a temporary substitution of the .ready jQuery method with a custom method during the processing of the Ajax response:

  1. var delayedExecution = [];
  2. var newReady = function (x) {
  3.     delayedExecution.push(x);
  4. };
  5. var oldReady = jQuery.fn.ready;
  6. jQuery.fn.ready = newReady;
  7. try {
  8.     //response processing here
  9. }
  10. finally {
  11.     jQuery.fn.ready = oldReady;
  12. }
  13. for (var i = 0; i < delayedExecution.length; i++)
  14.     delayedExecution[i]();

 

Where in most of the cases the response processing is just the call to the jQuery  .html method. Thus, we may define a widgetsHelpers.dynamicHtml(jTarget, html) that does the job of attaching an Html string to a jTarget node while ensuring that all JavaScript enhancements contained in the Html string are properly applied:

  1. widgetsHelpers.dynamicHtml=function(jTarget, html){
  2.     var delayedExecution = [];
  3.     var newReady = function (x) {
  4.         delayedExecution.push(x);
  5.     };
  6.     var oldReady = jQuery.fn.ready;
  7.     jQuery.fn.ready = newReady;
  8.     try {
  9.         jTarget.html(html);
  10.     }
  11.     finally {
  12.         jQuery.fn.ready = oldReady;
  13.     }
  14.     for (var i = 0; i < delayedExecution.length; i++)
  15.         delayedExecution[i]();
  16. };

 

 

However, we have another problem, too….Avoiding that the jQuery plug-ins that we apply to the newly added Html are re-applied also to the remainder of the Html page. In fact, if, for instance, we enhance all input fields contained in our dynamic Html that have the “datetime” CSS class with a Bootstrap datepicker, the datepicker plug-in would be re-applied also to the input fields of the remainder of the page  with the same attribute. Often jQuery plug-ins are robust and re-applying them to the same nodes doesn’t produce any effect. However, you can’t rely on this robustness, and, in any case, a similar solution would be very inefficient. The only way out is using different names….however, as we have seen in my previous post the code for generating datepickers is all contained into an unique Date.cshtml partial view that is called both by our initial page and by any other Ajax request.

Actually this is not the only “name convention” problem of Ajax provided content that we must solve! Normally, in Asp.net Mvc all input fields have names that MUST be strictly tied to the position where their content will be inserted in the ViewModel of the action method that the receive the data posted by the client. So for instance, a date that must be inserted, in the DateOfBirth property of Person instance inserted in the PersonalInfos property of the ViewModel MUST be rendered in an input field with name PersonalInfos.DateOfBirth, and id PersonalInfos_DateOfBirth, otherwise the default model binder wouldn’t be able to fill properly the ViewModel. The dot in the name is turned into an underscore in the id because the id can’t contain dots. Now, if the ViewModel used to render the page is the same as the model used to receive the post all above conventions are automatically enforced by the Asp.net Mvc Html helpers (TextBoxFor, etc.).

However, in general the ViewModel used by the Ajax controller differs from the one used for the initial page, since the Ajax call furnish just a part of the page data. So, for instance, in our previous example, if the Ajax call returns just the data obtained by rendering a Person object the name of our Date field would be DateOfBirth instead of PersonalInfos.DateOfBirth. Now if the Person data are submitted separately with another Ajax call to an Action method that uses a Person ViewModel all works ok, but if the Person data must be submitted together with the main page data we must add someway the PersonalInfos prefix.

Adding the PersonalInfos prefix to all input fields rendered by the partial view used by the controller that respond to the Ajax request is quite easy. It is enough to add the following code at the beginning of the View:

Html.ViewData.TemplateInfo.HtmlFieldPrefix = "PersonalInfos";

The prefix should be added just to the top level Partial View, since each time we call EditorFor and DisplayFor the Asp.net Mvc engine takes care of defining the right prefix for the child Partial View. However, in general the server doesn’t know this prefix, since the prefix depends on the role that the Ajax content will play in the overall page ViewModel. Suppose, for instance that the Html returned by the Ajax call must be used to add a new row to a grid, that contains Person data. The prefix to add should be something like AllPersons[i], where i is the 0 based index of the new row in the grid. So if the grid already contains 10, rows i=10, if the grid already contains 15 rows i= 15, and so on. In other terms only the client may know our prefix! So we must add the prefix as a further parameter of the Ajax call.

Unluckily the previous prefix, in general, cannot be used also to solve the problem we have with the datetime CSS class, because in the second case the CSS class must be unique withineach Ajax call not within a specific position in the ViewModel. Accordingly, for the CSS classes used to enhance the Ajax Html we might use a different prefix based on a count of all Ajax calls made to the server from the current Html page:

  1. (function ($) {
  2.     ...
  3.     ...
  4.     ...
  5.     var ajaxCount=0;
  6.     widgetsHelpers.newClassPrefix= function(){
  7.         return "classprefix"+(ajaxCount++);
  8.     };
  9. })(jQuery)

The two prefixes must be added to the parameters of the Ajax call together with the original request parameters, say,  personId, to get the final request URL:

ajaxRoot.attr("data-update-url")+"?personId="+personId+"&htmlPrefix="+htmlPrefix+"&classPrefix="+classPrefix

On the server side, any Ajax enabled controller must take care of receiving the two prefixes:

public ActionResult PersonData(int personId, string htmlPrefix, string classPrefix)
{
    if (!string.IsNullOrWhiteSpace(htmlPrefix)) ViewData[htmlPrefix]=htmlPrefix;
    if (!string.IsNullOrWhiteSpace(classPrefix)) System.Web.HttpContext.Current.Items["classPrefix"] = classPrefix;
    var model = repository.GetPersonById(personId);
    ...
    ...
    ...
    return PartialView(model);
}

 

The classPrefix has been added to the HttpContext dictionary, since it must be used by all Partial Views called in the current request, while the htmlPrefix has been added to the ViewData since it must be used just by the top level Partial View.

Now in the top level Partial View:

  1. @{
  2.     Html.ViewData.TemplateInfo.HtmlFieldPrefix = ViewData["htmlPrefix"] as string ?? "";
  3.     string classPrefix = System.Web.HttpContext.Current.Items.Contains("classPrefix") ?
  4.         System.Web.HttpContext.Current.Items["classPrefix"] as string + "-" :
  5.         "";          
  6. }

In the Data.cshtml Partial View, and in general in all Partial Views that might be involved in an Ajax call:

 

  1. @{
  2.     string classPrefix = System.Web.HttpContext.Current.Items.Contains("classPrefix") ?
  3.         System.Web.HttpContext.Current.Items["classPrefix"] as string + "-" :
  4.         "";          
  5. }

 

and then in each CSS class enhanced input field:

@Html.TextBoxFor(m => m.DateOfBirth, new {@class=classPrefix+"datetime"})

 

That’s all for now!

In the next post Json based Ajax calls and Single Page Applications.

Stay tuned!

Francesco

Tags: , , , , ,

Dec 10 2013

JavaScript Intensive Web Applications 2: Enhancing Html with JavaScript

Category: JavascriptFrancesco @ 06:35

JavaScript Intensive Web Applications 1: Getting JavaScript Intellisense

JavaScript Intensive Web Applications 3: Enhancing Applications with Ajax

jsFarmIntellisense 

There are mainly three ways you may improve your application with JavaScript, each with its vantages and disadvantages:

  1. Enhancing the page Html with JavaScript widgets
  2. Refreshing Html page areas with fresh Html returned by Ajax calls
  3. Creating Html dynamically using JSON returned by Ajax calls

In this post I will speak about the first technique that is the only one that has substantially no drawbacks. The other ones will be discussed in further posts of the same series.

In this and in all other posts of this series I assume that your web Application is implemented with Asp.net Mvc.

If we suppose that the application submits user inputs contained in Html input fields with standard form submits, JavaScript becomes just a tool that may  improve the appearance of the page and that may help the user to fill more easily the input fields. In other terms, it becomes a sort of “turbo CSS” we may use to improve the appearance and the user experience. This is the main idea that is behind all jQuery widgets that select Html nodes with CSS selectors and enhance them in a way similar to the way a CSS rule would do.

Unluckily, the “pseudo-styles” applied by jQuery widgets are not automatically enforced also on newly added Html, so jQuery widgets create problems when they are used together with Ajax techniques. We will analyze in detail these problems and how to solve them in the posts of this series dedicated to Ajax. In what follows I assume that no dynamic Html is added to the page, or that some small piece of Html that might be added automatically by some jQuery widget doesn’t need further enhancements by other jQuery widgets.

Do JavaScript enhancements have drawbacks? Since all browsers support JavaScript, …substantially no… if some simple cautions are adopted:

  1. You pay attention to cross browser compatibility. If you use jQuery and jQuery based frameworks like: jQuery UI, jQuery Mobile, Bootstrap, and Zurb Foundation this should be quite automatic.
  2. All Widgets that you use just enhance an existing Html. The basic functionality should be available, maybe with an awful unacceptable appearance, also if JavaScript is not supported. This requirements is not added for compatibility with browsers that don’t support JavaScript ….that don't exist anymore, but for compatibility with the search engines. If your application is an intranet, or if your page should not be available to search engines you may drop this point. Again if you use the above mentioned jQuery frameworks, and look at the specifications of further jQuery plug-ins you might use (most of the existing jQuery plug-ins conform to this requirement), and if you design properly your custom jQuery plug-ins, also this point should not be a problem.
  3. JavaScript enhancements must not undermine the accessibility of the page. This means all Widgets must use the right Html tags, and if needed, ARIA attributes. For instance, something that has the semantics of a list must be rendered with <li> tags also if it is enhanced with JavaScript. <table> …<tr>…<td> must not be used for layout but only for tabular data, if you need a table like layout, please use adequate CSS like display: table, and similar, instead. All widgets included in the jQuery frameworks I listed previously are ARIA compliant and conform to the requirements of this point.
  4. You use a well defined architecture, to avoid JavaScript “spaghetti code”. Architectures based on the idea of jQuery plug-in helps a lot but you need an effective way to organize all JavaScript modules used by the various pages. I will show you a trick based on require.js, and partial views  to add modularly as many JavaScript and CSS widget-files as you like, without undermining the maintainability of the application.
  5. You pay attention to the development time of each page and you avoid to fall into an endless loop of improvements with new, or better widgets.

All instructions that enhance the html must be executed after the DOM is ready, thus they may be inserted either at the end of the page Html body, or in the page header enclosed in a jQuery $(document).ready(….) handler.

Now, several “influencers” in the area suggest to insert all JavaScript at the end of the Html body and to avoid the use of .ready(). The reason is that any JavaScript placed in the page header slower the page rendering. However, most of the times I prefer the user see a white page loading instead of a page before that it has been enhanced by JavaScript because when you use complex widgets (a Tab widget is enough to show the phenomenon) the page may be unacceptable before its enhancement also if a search engine is able to understand its content :). For this reason I usually place all JavaScript libraries in the header (they are slow to load) and the page enhancing code at the end of the page body. This way, since usually the page enhancing code is quite fast the user see a blank page first, when all JavaScript libraries are loading, and after a fast adjustment (when the page enhancing code is executing) the final page.

I suggest to include all page enhancing code in a separate file, that should contains just lines of the type:

$("<selector>").myPlugin();

The file should contain just lines like the one above to keep the semantics of a “pseudo-CSS” file. This means that if you define custom widgets the widgets code should be included into a different JavaScript library file, that may be included in the page header together with all other JavaScript libraries.

The call to each plug-in should not contain any argument: all plug-in parameters  should be inserted in Html5 attributes. This way all enhancement calls become “standard” and may be created automatically by general purpose JavaScript code (see below). However, this implies that whenever you substitute a widget with another widget that performs the same job, you must modify also the Html; usually this is not a problem if you enclose the Html to be enhanced in a single server-module that is called in the remainder of the Html.  The example below, involving a Bootstrap datepicker, show how to proceed:

Html:

<input type="text" class="datepicker" value="02/16/12" data-date-format="mm/dd/yy" id="dp2" >

Enhancing JavaScript code:

$('.datepicker').datepicker();

 

 

 

 

The single line of JavaScript enhancing code above enhances all input fields with a datepicker CSS class. If you are using Asp.net Mvc, input fields with the datepicker class may be generated automatically with Html.EditorFor(…) if you define a Date.cshtml Mvc Template and if you decorate all DateTime properties that represent pure dates with a DateTypeAttribute  with a Date type value. This way any change to the datepicker parameters require just the change of the Date.cshtml file.

JQuery Mobile, Bootstrap and Zurb Foundation assign predefined classes and/or Html5 attributes to all predefined widgets and enhance them automatically on the .ready event, so you need to add an enhancing JavaScript file only if you use custom widgets. We will see the drawbacks of this approach when discussing Ajax techniques.

Event Handlers may be attached by specialized jQuey extensions, like in the example below:

 

$('.click-operation').clickHandler();

 

The click-operation class may be applied to all nodes that needs a click handler. Then, each single node might contain a data-event-operation Html5 attribute that specifies the specific operation to be carried out on that node. A possible implementation of the clickHandler jQuery extension is:

jQuery.fn.clickHandler = function () {
    this.click(function (evt) {
        switch (jQuery(evt.target).attr("data-event-operation ")) {
            case "op1": ....; break;
            case "op2": ....; break;
            ....
        }
        evt.stopPropagation();
    });
    return this;
}

I used evt.target, so the click handler may be used also for bubbled click events. Moreover, I called stopPropagation to avoid that the event is bubbled to a possible ancestor clickHandler.

Returning to the datepicker example. Since it is not part of the default widgets Bootstrap comes with, we might decide to substitute it with another widget. Imagine also that analogously we would like to substitute also other widgets with better implementations….Wow… a not easy job…we should modify a lot of JavaScript files included in all pages that contain the widgets we have substituted. If we were able to include the references to the datepicker JavaScript file in the same Date.cshtml  partial view that contain the Html of the datepicker it would be enough to make a few modifications to this file and in 10 minutes we would have a different  datepicker working. This way we might be able also to test easily several widgets.

The problem described above is a conceptual problem that is intrinsic in the the pseudo-CSS approach used to manage the Widgets. Widgets are conceptually different by style rules because style rules are part of a “closed specification” while widgets are not, so there are different widgets that do the same job, and new Widgets appears every day: the only way to deal with an “open set” is by enforcing modularity and by defining interfaces. In other terms we must enclose all code of a widget into an unique module that offers a standard interface to the remainder of the system.

Below a simple trick that solves the problem.Let add to the bottom of our Date.cshtml file the following snippet of code:

  1. <script type="text/javascript">
  2.     widgetsHelpers.initialize(["@Url.Content("~/Scripts/bootstrap-datepicker.js")"],
  3.                                 ["@Url.Content("~/Content/datepicker.css")"],
  4.                                 "datepicker",
  5.                                 ".datepicker")
  6. </script>

The first argument contains all JavaScript files(it is an array) with the needed code, the second argument the possibly null list  of CSS Urls that might be needed, the third argument the name of the jQuery plug-in method to call, and finally the selector that characterize all inputs that must be enhanced with the datepicker.

The implementation of the widgetsHelpers.initialize function uses the require.js library to load asynchronously the JavaScript files and is straightforward:

  1. (function ($) {
  2.     window["widgetsHelpers"] = window["widgetsHelpers"] || {};
  3.     var widgetsHelpers = window.widgetsHelpers;
  4.     widgetsHelpers.modules =
  5.         {
  6.             css: {},
  7.             js: {},
  8.             widgets: {}
  9.         };
  10.     function loadCss(url) {//load a Css file and adds it to the page
  11.         widgetsHelpers.modules.css[url] = true;
  12.         var link = document.createElement("link");
  13.         link.type = "text/css";
  14.         link.rel = "stylesheet";
  15.         link.href = url;
  16.         document.getElementsByTagName("head")[0].appendChild(link);
  17.     }
  18.     widgetsHelpers.initialize = function(js, css, widget, selector){
  19.         if (!widgetsHelpers.modules.widgets[selector]){
  20.             widgetsHelpers.modules.widgets[selector] = true;
  21.             $(document).ready(function(){
  22.                 if(css) {
  23.                     for (var i=0; i < css.length; i++)
  24.                         if(!widgetsHelpers.modules.css[css[i]]) loadCss(css[i]);
  25.                 }
  26.                 if (js ){
  27.                     var nJs = [];
  28.                     for(var i = 0; i<js.length; i++)
  29.                         if(!widgetsHelpers.modules.js[js[i]]) {
  30.                             nJs.push(js[i]);
  31.                             widgetsHelpers.modules.js[js[i]] = true;
  32.                         }
  33.                     if(nJs.length)
  34.                         require(nJs, function () {
  35.                             $(selector)[widget]();
  36.                         });
  37.                     else{
  38.                         $(selector)[widget]();
  39.                     }
  40.                 }
  41.                 else{
  42.                     $(selector)[widget]();
  43.                 }
  44.             });
  45.         }
  46.     };
  47.     widgetsHelpers.loadCss = loadCss;
  48. })(jQuery)

We create a namespace, than we create the dictionary widgetsHelpers.modules to “remember” the JavaScript, CSS files and modules that have been already loaded. The loadCss function loads all CSS files that cannot be loaded with require.js.

Finally the initialize function, verifies if another call has already required the same widget, and, if not, on the .ready event loads both the needed CSS and JavaScript files (if not null and if not already loaded), then it applies the widget on the provided selector.

In case  a single partial view needs a JavaScript module containing the definitions of several widgets we may use the widgetsHelpers.intializeAll instead:

 

  1. widgetsHelpers.initializeAll = function(js, css, widgetsArray, selectorsArray){
  2.     widgetsHelpers.intialize(js, css, widgetsArray[0], selectorsArray[0]);
  3.     for(var i=1; i<widgetsArray.length; i++) widgetsHelpers.intialize(
  4.         null, null, widgetsArray[i], selectorsArray[i]);
  5. };

widgetsArray and selectorArray are arrays that contain respectively all widget names and all jQuery selectors used to reference these widgets from the Html nodes. The JavaScript file and the CSS files are passed just in the first call to initialize, while all other calls are needed just to create the pseudo-CSS rules.

The same partial view may contain several calls to initialize and/or initializeAll in case the widgets are split in different files.

That’s all for now!

In the next post all secrets of Ajax based applications…and new useful tricks.

Stay tuned!

Francesco

Tags: , , , , ,

Dec 2 2013

JavaScript Intensive Web Application 1: Getting JavaScript Intellisense

Category: JavascriptFrancesco @ 03:43

JavaScript Intensive Web Applications 2: Enhancing Html with JavaScript

JavaScript Intensive Web Applications 3: Enhancing Applications with Ajax

This is the first of a series of tutorials on the use of client techniques in Web Applications. We will discuss when it is convenient to use Ajax, or JavaScript intensive Web pages, or Json communication or Single Page Applications, and how to solve some typical “nightmares” that these techniques bring with them.

In this first tutorial we will try to remove (or just to lower…) one of the main barriers that discourages the development of large JavaScript codebases: the absence of syntax checks and Visual Studio Intellisense comparable with the ones we have in other strongly typed languages.

Actually Visual Studio and a lot of other JavaScript editors are able to signal immediately pure syntax errors. The main problem is that they are not so smart also in inferring types, and  consequently in furnishing adequate intellisense. The reason of this incapability are basically two:

  1. JavaScript is a dynamic, not strongly typed language. This means that the same variable or function parameter may store different data types, and that consequently the JavaScript editor cannot rely on the variable/parameter data type to perform type checking and to give adequate intellisense.
  2. JavaScript contains no concept of module  reference and/or linking, so a JavaScript file comes to know all details about external functions and prototypes only at run-time when all needed modules are for sure available.

Visual studio offers tools for resolving easily the second problem: namely when you are in a JavaScript file you may add some kind of references to other JavaScript files used by the current module by using the syntax of Xml comments. Xml comments are JavaScript comments composed by /// followed by adequate Xml expressions. Since they are comments they are ignored by both JavaScript minifiers and JavaScript's interpreters.

The syntax for a JavaScript reference Xml comment is basically:

  1. /// <reference path="/path/subpath/..../JavascriptFileToReference.js" />

We may use also “~” to denotes the root of our web application.

When we are editing a JavaScript file, it is enough to drag the file we would like to include from the Solution Explorer to the file we are editing to get automatically the reference Xml comment.

If a JavaScript file is included in an Html page or .cshtml page there is no need to reference it also with a reference Xml comment to get JavaScript help on its code. However, often Html, or .cshtml files use JavaScript files that they don’t include directly for different reasons such as: 1) they might use code retrieved via AMD, 2) the JavaScript files might be included in a _Layout page or in another .cshtml page in case they are partial views, 3) the .cshtml file might be used to produce a dynamic JavaScript file, instead of an Html page.

In all above cases we may use a reference Xml comment inside the <script> tags that enclose the JavaScript code. However, unluckily, in this case we can’t drag the file to reference but we have to insert the reference Xml comment manually.

So now we are able to reference JavaScript library to get intellisense…so the problem now is to to actually get intellisense on each JavaScript variable. While JavaScript is not strongly typed, starting from Visual studio 2012, the JavaScript intellisense improved a lot, and now Visual Studio is able to infer the type that should be contained in a variable from the previous code. For instance if you write:

(function () {
    var simpleOperation = function () {
        this.mult = function (x, y) {
            return x * y;
        };
    };

and then:

  1. var operation = new simpleOperation();

Then we get help on the variable operation:

jsNewIntellisense

We get the same help also if the object is returned by a farm function:

(function () {
    var simpleOperationFarm = function () {
        return{
            mult: function (x, y) {
                return x * y;
            }
        };   
    }
    var operation = simpleOperationFarm();

 

jsFarmIntellisense

 

 

 

 

 

In general Visual Studio >= 2012 do the best to infer a type from a static analysis of the code. However, very often static analysis is not able to infer types in a dynamic language like JavaScript.

However, we may use a couple of tricks to “pass” to Visual studio the information on the types contained in a variable or parameter.

The first trick may be applied to the parameters of a function: immediately after the parameters declaration we may place a param Xml comment:

function (operation) {
        /// <param name = "operation" value = "new simpleOperation()"/>

The value attribute may contain any JavaScript expression, but typically we put, a creation operation, a farm function, a simple value (such as an integer, or a string), an array, an object, or nested arrays and objects. Below, a suitable value to get help on objects that are elements of an array:

paramsIntellisense1

 

Notwithstanding some syntax error…we get our intellisense!

We might obtain a similar result also with:

function (operation) {
    /// <param name = "operation" value = "[{mult: function(x, y){}}]"/>

 

 

Now we are able to get help on each function parameter…but often knowing the type of the function parameters is not enough to infer the type of each variable that is local to that function, or the type of an object manipulated by the function…(for instance because they were not passed as a parameter, but it is part of the function closure). Moreover, sometimes JavaScript functions accept parameters that may take several different types.

Now, we may call a method or to read/set a property of an object in a given place of a JavaScript function only if we know that in that part of code a member or variable must necessarily contain a given type, because we must be sure the property or method we are referring to actually exists! Thus, let suppose that we know that in some part of our code the type of the variable operation, or the type of the member mayObject.operation must be SimpleOperation, then we may enclose  that part of our code in a function:

 

 

(function (..., operation, ...) {
    /// <param name = "operation" value = "new simpleOperation()"/>
    // now we may get intellisense
    ...
    ...
    ...
})(..., myObject.operation, ...);

 

 

in case we can’t enclose the code inside a function we may use this other trick:

 

myObject.operation = myObject.operation || new simpleOperation();

 

Since we supposed we are sure myObject.operation contains a simpleOperation,  the second operand of || will never be evaluated, so our instruction do simply…nothing but helping VisualStudio to infer the type of myObject.operation .

Needless to say the second operand of the above || may contain the same kind of expressions of the value attribute of the param Xml attribute.

The above tricks enable us to get intellisense in any situation! Thus the main nightmare of JavaScript coding has been “mitigated”!

 

That’s all for now!

In the next post a deeper analysis of JavaScript intensive Web techniques.

 

Stay tuned!

Francesco

Tags: , , , , ,