Sunday, September 26, 2010

Javascript Functions for Dummies

A common confusion is when to use "function", "new function" and "new Function"

1. Plain "function" is simply code that does a particular task. It can be called directly or by an event (similar to module/procedure/subroutine in other languages). It typically returns a value.
function AreaOfCircle(r){
return Math.PI*r*r;
}
//Now call the function as:
alert(AreaOfCircle(3));

You can declare an anonymous functions as:
function(){
...
}

You can declare the function and execute it immediately. For example:
alert(
function(){
alert("executing function...");return "done!";
}() //execute function, and alert the returned value
);

Note:
function Foo(){ ... }
is shortcut for:
var Foo = function(){ ... }
//Creates an object with code which can be called as Foo();


Check this out:

var x=function f(){};
console.log(x?true:false)
console.log(x()?true:false)

The first one will return true, as "function" is like an object and returns "truthy". the second one OTOH executes this empty function and returns "undefined", which essentially is "falsy".

2. The "new" keyword basically returns an object based on the code specified inside the function.
var o = new function(){...} is shortcut for:
function Foo()
{
this.x = 1;
this.y = 2;
}
var o = new Foo;

This creates an object "o" with two properties: x and y. Basically this does the exact same thing as the two examples below:
//Object instantiation
var o = new Object();o.x=1;o.y=2;
//A more compact Object Literal Notation:
var o= {x:1,y:2};


3. Finally, there "Function constructor" which allows you to create a function by passing strings for function-parameters and function-code:
var a=new Function("x","y","alert(x+y)"); //last string is the code
a(3,4); //results in "7"

Note the capital "F" in the function constructor. Also note this constructor does not create a closure.

Object-oriented javascript tutorials can be found at: mckoss, javascriptkit, and sitepoint

More javascript essential study material: Douglas Crockford YUI videos on JS reintroduction. And if you are feeling confident, go take the javascript quiz on kourge.net - you'll be humbled pretty quickly!

Wednesday, August 4, 2010

Sending HTML content to an asp.net MVC View

I have co-authored an article in the upcoming print issue of Visual Studio magazine(VSM). This covers asp.net MVC 2.0 and data annotations for the vb camp.

I happened to be reading one of Joe's blog where shows how to read HTML snippet from an external file and send it to a View. I got thinking on different ways to achieve this result. One good way way to sharpen your coding skills is to try and figure out different ways to solve the same problem. I posted my response as a comment, but I think that this deserves more discussion, so here we go...

Joe's suggestion is to read the text/html into a string and then dump it into the ViewData dictionary, which is a standard way of passing data from a Controller to a View, which is probably the easiest way to take html snippets and embed them into your page. A word of caution: when you send HTML to a browser to display, you need to have checks to ensure that no malicious html/javascripts get through(especially if it is user-generated content). CSRF, XSS and Clickjacking are among the top ten security threats in 2010. In this case the usual defense of html-encoding will will not work as it defeats the very purpose of wanting to render the HTML.

I will discuss several other methods. The most direct way is to call the ReadAllText method from the View, and the content of the snippet gets dumped on the fly:

<div id="snippet_container" style="border:2px solid black">
<%= System.IO.File.ReadAllText(@"C:\temp\snippet.htm") %>
</div>

A second way to insert snippets is to create an Action whose job it is to return a string, and then you can just call RenderAction helper method.

<%Html.RenderAction("ShowSnippet",
new { filename = @"C:\temp\snippet.htm" }); %>

You can dynamically change the "filename" parameter to display any file, or insert any parameter into the ShowSnippet Action method, for that matter. The action will look like:

[ChildActionOnly]
public string ShowSnippet(string filename)
{
return System.IO.File.ReadAllText(filename);
}

Put the ChildActionOnly Attribute if you don't want the Action to be called directly. I can see lots of possibilities with this technique. You can pass any number or parameters and do all kinds of processing, such as call a web service, or build HTML dynamically from complex data. This is one way of creating widgets.

A third way is to create a View-Model, where you populate all data required by the View. There are many blogs on the subject, so I won't spend much time discussing it.

A very cool way fourth way for dynamic content is using the Ajax. This topic is too large and not the focus of this blog, so I will show you one easy way and move on. The Ajax.ActionLink helper method shown below will display content inside the specified container. You will need to insert references to the scripts: MicrosoftMvcAjax.js and MicrosoftAjax.js:

<%= Ajax.ActionLink("Click to insert snippet", "ShowSnippet",
new AjaxOptions { UpdateTargetId = "snippet_container"}) %>
<div id="snippet_container" style="border:2px solid black">snippet results go here</div>

The possibilities with Ajax are endless! If you want to just output text/html (not embed it in a View), you can simply return a string, similar to the action method shown above. You don't need a View, the string will render as html. Here are some other ways to do it, non of which require a View:

1. Return a "FileResult" - there are many ways to do this. You can use this to return any type of content, not just html.

public ActionResult myhtml1(){
return Content(System.IO.File.ReadAllText(@"C:\stuff.htm"));
return this.File(@"C:\stuff.htm","text/html"); //"File" is a method of the controller
return new FilePathResult(@"C:\stuff.htm","text/html");
return new FileStreamResult(System.IO.File.OpenRead(@"c:\stuff.htm"), "text/html");
}

2. An even simpler way: this does not have to be an MVC Action, and will work with traditional asp.net applications as it it uses a standard Response object.

public void myhtml2(){
Response.WriteFile(@"C:\stuff.htm");
}

Response.Write() and Response.TransmitFile() are similar to the WriteFile() method. Here is a cool way to steal, ahem, borrow content from some other website and pipe it to a Response:

public void myhtml3(){
var wreq = System.Net.WebRequest.Create("http://jbknet.blogspot.com/");
var wresp = wreq.GetResponse();
var sr = new System.IO.StreamReader(wresp.GetResponseStream());
Response.Write(sr.ReadToEnd());
}

For completeness sake, I will add that if you want to simply forward(redirect) the request:
1. You can use the Response.Redirect or Server.Transfer methods in your action
2. Put the "Refresh" Meta tag in your View or
3. Put Javascript forwarding code in your View (location.href or location.replace)

Monday, July 26, 2010

JS tips - I

Level: Moderate

String to integer conversion (Caution with parseInt):

Remember to always include the base with parseInt, otherwise you can introduce hard to find bugs. If the string has a leading zero, it is evaluated with base 8 (Octal). Therefore "015" will return 13. The correct way is parseInt('015', 10);

A neat way is to achieve the same is to simply put a plus sign in front of the string variable. That forces a type conversion to decimal:
var s="015"
var i= +s + 2;
console.log(typeof i);
console.log(i);
//results in:
// number
// 17

Trim() for strings:

You can extend the String object to include trim, ltrim and rtrim with a little regex to strip off the surrounding white spaces.

String.prototype.trim = function() {
return this.replace(/^\s+|\s+$/g, '');
};
String.prototype.ltrim = function() {
return this.replace(/^\s+/, '');
};
String.prototype.rtrim = function() {
return this.replace(/\s+$/, '');
};


Now you can use trim any string variables, input field values, or even string literals. For example:

<input id="firstname" onchange="value=value.trim()" />

Sunday, July 25, 2010

Fun with Javascript Dates III

Level:Moderate

Javascript Date objects can be created with the following parameters:
new Date(year, month, date, hours, minutes, seconds, milliseconds)
If you only specify the first two parameters, all others are assumed to be zero.
This date instantiator has a very interesting feature. The parameters for month, date(i.e. monthday), hours etc do not have the standard upper and lower bound. They can be any integer. For example monthday can be negative or greater than 31.

var d = new Date(2010,0,1) // will yield 1st Jan 2010
var d = new Date(2010,0,-2) // 29 Dec 29 2009 (back 3 days)
var d = new Date(2010,0,-2, 100) //1st Jan 2010, 4am (minus 3 days plus 100 hours)

This was a very cool design decision, because now it becomes very easy to perform date addition.

1. Add/Subtract days and months etc to a date

var d = new Date(); //today's date
var d2=new Date(d.getFullYear()+3,d.getMonth()+4,d.getDate()+5)
//d2 is set to 3 years, 4 months and 5 days in the future

Better still, we can extend the Date Object’s behavior and add this functionality.

Date.prototype.addDays = function(days) {
return new Date(this.getFullYear(),this.getMonth(),this.getDate()+(+days))
}
//See my ParseInt blog if you think the (+days) is odd looking
//Usage:
//var now = new Date();
//var Yesterday = now.addDays(-1);
//alert(Yesterday);

I’ll leave it up to you to implement addMonths() and addYears(), Hours, Minutes, Seconds.

2. Day of the Year: (Julian Day)

Date.prototype.getDOY = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((this - onejan) / 86400000);
}

3. Week of Year

Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
}

4. Fiscal Year if your new year starts on October 1st of the previous year.
We can use the addDays() prototype function we just created!

Date.prototype.getFiscalYear = function() {
return this.addDays(92).getFullYear();
}

Datejs library on googlecode, has amazing functionality added on to the Date object. Many other major frameworks have similar libraries.

Friday, July 23, 2010

Fun with Javascript Dates - II

1. Javascript Date object has many differences from .Net DateTime type. Some of the prominent differences are:
  • Month is zero based integer (0 to 11) - this can be a source of many a bug.
  • Weekday (getDay) returns 0-6 for Sunday-Saturday

    To get descriptive weekday, you can extend the date object's functionality like so:

    Date.prototype.getDayShort=function(){
    return ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][this.getDay()];
    }
    //Test it:
    alert((new Date(2010,1,1)).getDayShort())

    This will popup "Mon". Some of you are looking up the calendar and thinking "shouldn't 1st Jan be a Friday". No Siree, the date is 1st Feb -- did you already forget my month's tip above? I will leave it up to you to implement a getLongDay() function.

    The cool trick above is declare a lookup array on the fly. It saves a line of code, and an additional variable, and can be useful for small, one-time-use lookups. You can use the same trick with JSON objects. For example:

    alert({black:"#000000", blue:"0000ff", red:"#ff0000"}["blue"]);

    2. One biggie is the Y2K bug. Javascript and .Net have methods to create date objects from numbers. Javascript's Date(yy,mm,dd) constructor will treat all 2 digit year to be 19th century, while .Net has DateTime.Parse method which assumes years "0" to "29) to be 20th century. To mimic .Net's behavior check for date under 30, and add 2000, as shown below:

    for(var i=0;i<102;i++)
    console.log(new Date(i<30?i+2000:i,1,1));
  • Thursday, July 22, 2010

    Fun with Javascript Dates

    I'm going to start a series on Javascript. I'm gonna post some cool and useful solutions that are not currently available on the internet (as far as I know).

    Let's start small. Here is a function that will truncate the Time component from a date object. This can be useful when doing date comparisons, inadvertent bugs are introduced because of the time component.


    <script type="text/javascript">
    function removeTimeFromDate(inDate){ //i.e. set date to Midnight
    return new Date(Date.parse(inDate.toDateString()));
    }
    //Test it out:
    var now = new Date();
    alert(now);
    alert(removeTimeFromDate(now));
    //Results:
    //Thu Jul 22 2010 23:37:50 GMT-0400 (Eastern Daylight Time)
    //Thu Jul 22 2010 00:00:00 GMT-0400 (Eastern Daylight Time)
    </script>


    Pretty simple, once you see it, yet most people write a ton of code to achieve this functionality. Another way is to return a new Date(inDate.getFullYear(), inDate.getMonth(), inDate.getDate())

    You can add this functionality to the Date object itself, thereby extending it. I will show you how to do this in the next post.

    Saturday, May 22, 2010

    Substring Extension Method that does not give exception

    One of the limitations of the .Net Substring(start,[length]) method is it expects the arguments to be within range otherwise we get ArgumentOutOfRange. This is by design as strings are immutable, a member function doesn't exist. String manipulation is one of the most common activity, and it becomes huge annoyance when your truncate or some other method fails at runtime. You may have to write additional code to guard against range "overreach".

    Here is a wonderful extension method (IMHO) that solves your substring overreach issue once for all -- instead of runtime exception, it instead returns the most logical substring based on parameters and substitutes nulls for anything beyond that range -- including an empty string if the whole thing is beyond the range.

    Substring(startIndex, handleIndexException)
    and Substring(startIndex, length, handleIndexException)

    "startIndex" and "length" work just like the original substring. But with handleIndexException enabled(set to TRUE) is where the behavior gets interesting:


  • "startIndex" can be negative or can exceed length of string.
  • "length": when negative is interpreted as take characters from the left. Therefore, Substring(2,-1,true) means start from third position (remember C# count is zero-based), and take one character from the left. See extensive examples below.

    Note, I created another extension method to show nulls. Also I tested it with all possible boundary conditions. Attached are the test results.

         /// 
         /// String Extension for Substring with startIndex, that intelligently handles out of bounds without returning exception
         /// see http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html
         /// 
         /// 
         /// 
         /// 
         /// if set to "true" handles intelligently handles the exception, otherwise works like regular Substring
         public static String Substring(this String val, int startIndex, bool handleIndexException)
         {
             if (handleIndexException)
             {
                 if (string.IsNullOrEmpty(val))
                 {
                     return val;
                 }
                 int instrlength = val.Length;
                 return val.Substring(startIndex < 0 ? 0 : startIndex > (instrlength - 1) ? instrlength : startIndex);
             }
             // ELSE handleIndexException is false so call the base method
             return val.Substring(startIndex);
         }
    
    
    
    /// /// String Extension for Substring with startIndex and Length, that intelligently handles out of bounds without returning exception /// see http://jagdale.blogspot.com/2010/05/substring-extension-method-that-does.html /// /// /// /// /// /// if set to "true" handles intelligently handles the exception, otherwise works like regular Substring public static String Substring(this String val, int startIndex, int length, bool handleIndexException) { if (handleIndexException) { if (string.IsNullOrEmpty(val)) { return val; } int newfrom, newlth, instrlength = val.Length; if (length < 0) //length is negative { newfrom = startIndex + length; newlth = -1 * length; } else //length is positive { newfrom = startIndex; newlth = length; } if (newfrom + newlth < 0 || newfrom > instrlength - 1) { return string.Empty; } if (newfrom < 0) { newlth = newfrom + newlth; newfrom = 0; } return val.Substring(newfrom, Math.Min(newlth, instrlength - newfrom)); } // ELSE handleIndexException is false so call the base method return val.Substring(startIndex, length); } //TEST IT: //Console.WriteLine("-1,3 : " + "abcde".Substring(-1, 3, true).ShowNull()); //....etc... RESULTS from a suite of tests for the string "abcde":
    start,length:result
    ===================
    -1 : abcde
    -0 : abcde
    2 : cde
    4 : e
    5 : <<null>>
    12 : <<null>>
    -1,-1: <<null>>
    -1, 0: <<null>>
    -1, 1: <<null>>
    -1, 3: ab
    -1, 9: abcde
    0,-1: <<null>>
    0,-0: <<null>>
    0, 3: abc
    0, 9: abcde
    2,-3: ab
    2,-2: ab
    2,-1: b
    2,-0: <<null>>
    2, 2: cd
    2, 6: cde
    4,-9: abcd
    4,-4: abcd
    4,-0: <<null>>
    4, 1: e
    4, 4: e
    5,-9: abcde
    5,-5: abcde
    5,-4: bcde
    5,-0: <<null>>
    5, 1: <<null>>
    I hope this helps. I spent several hours first browsing the web, then writing/testing the code. This can be a great time saver!