Using Extension Methods With Typed Datasets

DataTable is one of the most widely used classes in .NET framework. In data layers of a typical ADO.NET application one can see lot of code to work with DataTable and DataRow. In this article I discuss how to do some common tasks involving datasets in more fashionable manner, in LINQ style. This is not a tutorial on LINQ or extension methods or typed Datasets.

I am assuming that most of you already know lot more about them than I do (if not, don’t worry there are always late starters like me :-) ). So, the first question is why only ‘typed’ datasets ? why isn’t this article covering normal datasets. To answer this question, let use create a typed dataset using VS2008 I have created the following dataset, it has two tables:

In .NET 3.5 all tables of a typed dataset inherit TypedTableBase, which in turn implements IEnumerable. If you have been reading about .NET 3.5 stuff, you will realize that this is the interface that has many powerful extension methods defined for it. This enables us to use LINQ’s extension methods with our DataTable classes. If this doesn’t excite you, go thorough the code snippets below:

1. Filtering Rows

The traditional way:

1
DataRow  pr = p.Person.Select("Firstname ='a'");

With extension methods:

1
var prst = p.Person.Where(n => n.FirstName=="a").ToArray<Persons.PersonRow>();

2. Joining tables to get data

Suppose we want to get all PersonInfo rows for persons whose first name contains ‘a’. Now imagine writing C# code for that without use extension methods, and compare it with this:

1
2
3
4
var onlyinfo = p.Person.Where(n=>n.FirstName.Contains('a')).Join(p.PersonInfo,
n => n.PersonId,
m => m.PersonId,
(n, m) => m).ToArray<Persons.PersonInfoRow>();

3. Summing up a particular column

To get sum of all Ids (kinda of vague but just for example :-))

1
int sumofids = p.Person.Sum(n => n.PersonId);

4. Getting a set of continus rows

Get row no. 3, 4 and 5

1
var x= p.Person.Skip(2).Take(3);

5. Sorting by a particular field

Sorting by last name

1
var o = p.Person.OrderBy(n => n.LastName);

Sort by “LastName,FirstName”

1
var y = p.Person.OrderBy(n => n.LastName+","+n.FirstName).Reverse();

6. Join using LINQ syntax

Here we join two tables using LINQ syntax. What the query does is fetches custom resultset for all persons whose PersonId < 5

1
2
3
4
5
6
7
8
9
10
11
var tm = from l in p.Person
join q in p.PersonInfo
on l.PersonId equals q.PersonId
where l.PersonId < 5
select new { l.PersonId, q.PersonInfoId, l.FirstName, l.LastName };

var myarr = tm.ToArray();

Console.WriteLine("{0} {1} {2} {3}",
myarr[0].FirstName, myarr[0].LastName,
myarr[0].PersonId,myarr[0].PersonInfoId);

These were just some examples of what you can do with typed datasets .NET 3.5. In many cases, using extension methods will reduce the amount of code you write drastically.

Creating self updating animated charts with Fusion Charts and ASP.NET

See Live Demo | Download Source

In this article I will show you, how to create cool self-updating charts using Fusion Charts , ASP.NET and some AJAX. If you are getting impatient to see how they look, click here to see a demo. You should read this article if :

  • You want to integrated animated charts into your ASP.NET pages.
  • You are looking for free and feature rich charting tool.

About Fusion Charts

Fusion Charts is a flash based charting package that can be used with almost any server side programming language. The free version of their charts includes some 22 different types of charts which can be animated. The best part of the free version is,it comes with unbelievably liberal license agreement, which allows you to use them even in your commercial applications. You can read the license for free version here: http://www.fusioncharts.com/free/TermsOfUse.asp .

Downloading and Installing Fusion Charts

  • Download ‘Fusion Charts Free’ from this link. Before downloading please read the terms of use.
  • Download my source code and unzip to a folder, say C:\…\SelfUpdatingCharts\
  • Open the C:\…\SelfUpdatingCharts\ folder as a website in VS 2008 or VWD 2008.
  • Unzip the fusion charts zip file and copy contents of ‘Charts’ folder (all *.swf files) to C:\SelfUpdatingCharts\Charts folder.
  • Copy the FusionCharts.js file from C:\..\..\FusionChartsFree\JSClass folder to C:\SelfUpdatingCharts.

After performing the above steps your solution explorer would look like attached image.

Thats it! we are all set up. After this step you should be able to run the Charts.aspx file and see the charts in action. In the remaining part of article, I will discuss step by step how to include charts in a newly created page.

Creating a new *.aspx Page

Create a new *.aspx page. Add a script manager to it. Make sure that the ‘EnablePageMethods’ property is set to ‘true’.This is required, since we will be using WebMethods via AJAX to fetch data for our graph at regular interval.Now add a reference to the FusionCharts.js file in our new aspx page. Somewhere on the page create a DIV tag and assign it an id of “mychart”. We will use Fusion Chart’s javascript API to create and display a new bar chart inside this div.

Writing server side code

I am going to create a six data point bar chart. So we write a “WebMethod” in the code behind ,which returns an array of six numbers. The code is simple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[WebMethod]
public static string GetDataForBarChart()
{
if (IsDataChanged(20) || HttpContext.Current.Session["StartedBC"] ==null)
{
StringBuilder sb = new StringBuilder();
Random r = new Random();
sb.Append(r.Next(2000)); sb.Append(",");
sb.Append(r.Next(2000)); sb.Append(",");
sb.Append(r.Next(2000)); sb.Append(",");
sb.Append(r.Next(2000)); sb.Append(",");
sb.Append(r.Next(2000)); sb.Append(",");
sb.Append(r.Next(2000));
HttpContext.Current.Session["StartedBC"] = 1;
return sb.ToString();
}
else
{ return "NULL"; }

}
private static bool IsDataChanged(int someid)
{
Random r = new Random();
int i = r.Next(10);
return (i % 9 == 0)?true:false;
}

The code is pretty straightforward, except for the ‘IsDataChanged’ and ‘Session’ part. The first one is a function that in real world scenario would hit database and check if there are any changes. If no changes were recorded after last request, it would return “NULL” instead of returning data. In this way I have tried to preserve bandwidth and prevent the charts from updating unnecessarily. The code involving session object makes sure that data is always transmitted for the very first time. There can be various ways of achieving this, this is my method.

Writing the javascript

The javascript for chart can be divided into three parts. The first one creates the chart object, second one does AJAX to get new data and last one generates XML required for binding to the data returned by server. One thing I want to tell here is, you can directly return XML from the server, instead of CSV. I used CSV, because I felt it was lighter and XML generation could be handled at the client end using javascript. Given below is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script  type="text/javascript"  src="FusionCharts.js"></script>
<script type="text/javascript">
function init()
{
var chart1 = new FusionCharts("Charts/FCF_Column3D.swf", "chart1Id", "500", "400");
chart1.setDataXML("<graph></graph>");
chart1.render("mychart");
PageMethods.GetDataForBarChart(OnCompleteBarChart,null);
}

function OnCompleteBarChart(a)
{ if(a != "NULL")
updateChartXML("chart1Id",GenerateXMLForBarChart(a));
window.setTimeout("PageMethods.GetDataForBarChart(OnCompleteBarChart,null)",10500);
}

function GenerateXMLForBarChart(x)
{
var arr = x.split(",");
if(arr.length==6)
{
var xml= "<graph caption='Page Visits Summary' subcaption='For the year 2009' xAxisName='Month' yAxisName='Page Visits' yAxisMaxValue='2100' >";
xml+="<set name='Jan' value='"+arr[0]+"' color='AFD8F8' />";
xml+="<set name='Feb' value='"+arr[1]+"' color='F6BD0F' />";
xml+="<set name='Mar' value='"+arr[2]+"' color='8BBA00' />";
xml+="<set name='Apr' value='"+arr[3]+"' color='FF8E46' />";
xml+="<set name='May' value='"+arr[4]+"' color='008E8E' />";
xml+="<set name='Jun' value='"+arr[5]+"' color='D64646' />";
xml+="</graph>";
return xml;
}

}
</script>

The first function, ‘init’ is called on the ‘onload’ event of body. It creates a new ‘Chart’ object by specifying the path of swf file ,id of the chart and its dimension. The ‘FCF_Column3D.swf’ file creates a 3D bar chart for us. Immediately after creating the chart we assign it empty XML and make an AJAX request using PageMethods object. When the response of our request arrives, ‘OnCompleteBarChart’ gets called, which in turn calls ‘GenerateXMLForBarChart’ and updates the bar chart display. One important thing to note here is that the format of XML varies depending upon the chart type. You can have a good idea of the XML for various chart types by checking examples provided with Fusion Charts. The ‘GenerateXMLForBarChart’ method takes a CSV string returned by server and transforms it into XML required for the graph.

Thats all!

Now run the page, you should be able to see the chart. In my code, I have specified a timeout of 10500 ms between two AJAX calls for updating the chart. This should be sufficiently high, other wise the chart would refresh before. Thanks for reading. Hope you found it useful. For suggestions,questions or criticism , please drop a comment.

Self updating animated charts with Fusion Charts and ASP.NET Demo

Go back to the article.

Javascript Based Demo

This is a javascript based demo of the sample application.

This demo uses Fusion Charts Free available under following licensing terms: http://www.fusioncharts.com/free/TermsOfUse.asp init();

Using Client-Side Custom Events in ASP.NET Applications

Download Code

These days many average developers like me find themselves breaking their heads to implement ‘desktop like’ behaviors for web applications. Many ASP.NET controls (like Button and ModalPopupExtender) have public properties for attaching javascript handlers to client side events. Now a common problem is,

"you want to notify multiple controls about an client side event."

For example:

  • When value inside some control of a grid changes , sum and average needs to be calculated and displayed.
  • You may want to perform validation and few calculation on ‘click’ event of an ASP.NET ‘button’ control.

In more complex scenarios, it might be required to be able to dynamically add and remove handlers, in addition to things mentioned above. I have seen developers do lot of ugly ‘wiring’ of javascript functions to achieve this. Of course it works , but it is a nightmare to maintain. In this article we will see how to make use of ‘client-side custom events to simplify coding for such scenarios.

What are ‘Client-Side Custom events’ ?

DOM elements have some standard events defined, like ‘click, onmouseover, onblur..etc’ . But what if we wanted to define new event that didn’t exist and use them (just like we do in C# ). The answer to this is ‘custom events’. There are many javascript libraries which make it possible to create and use custom events. In this article I will use jQuery, since it is believed to be supported in next version of Visual Studio. Custom events are similar to once we use in C# or VB.NET coding. We basically think of an event name, attach one or more handlers to this event and raise the event whenever required.

Sample Scenario

I have taken up a very simple scenario, where I will show how use of custom events make things pretty as opposed to tradition methods. I have a grid like display , where each row performs a specific operation on value input by the user using a AJAX modal popup. Attached below is the screen shot. When the user brings up the modal dialog box , enters value and clicks ‘OK’ following things happen:

  • Input is validated.
  • In first row results of the operation : value * 2 is displayed.
  • In first row results of the operation : value + 2 is displayed.
  • In first row results of the operation : value / 2 is displayed.

Screenshot of the sample application.

Doesn’t look like a big deal ! So why use custom events, when it is lot easier to write a single function to do all this, and hook it up to ‘OnOkScript’ property of the ModalPopupExtender. We could do that , but what if , we had 20 such operation ? wont a single function be too long and complex ? And what if we wanted the ability to add/remove handlers dynamically? In the above screen , I have placed checkboxes to facilitate dynamic attaching /detaching of handlers.

Using Custom Events

For the above scenario, I thought of an custom event named ‘okbuttonpressed’ . To the ‘OnOkScript’ property of the modalpopupextender, we assign the ‘GetNumber()’ javascript function. Given below is the code:

1
2
3
<ajaxToolkit:ModalPopupExtender PopupControlID="Panel1" ID="ModalPopupExtender1" runat="server" 
TargetControlID="Button1" CancelControlID="btnCancel" OkControlID="btnOK"
BackgroundCssClass="modalBackground" OnOkScript="GetNumber();" >
1
2
3
4
5
6
7
8
9
function GetNumber()
{
var i = $("#txtVal")[0].value;
var val = parseInt(i);
if( val != i)
{alert("Please enter a valid integer.");$("#txtVal")[0].value=0;}
else
{ jQuery(document).trigger('okbuttonpressed', val);}
}

Here , ‘txtVal’ is id of a texbox inside the modal popup where user enters a value. As a best practice, I should have tried to fetch ‘ClientId’ (since its a severside control) and use it, but since we are not dealing with repeaters and usercontrols , I am using the id directly (also because I am bit lazy). So when ‘OK’ button is clicked , the above function gets called and the ‘okbuttonpressed’ custom event gets triggered.

Attaching handlers to custom events

On check/uncheck of a checkbox in any row, I have written code to attach /detach a handler for the custom event ‘okbuttonpressed’ . For example, when ‘chkAdd’ is selected, we attach a handler ‘AddVals’ . Here is complete code:

1
2
3
hkAdd.Attributes.Add("onclick", "AddChkChanged(this)");
chkMul.Attributes.Add("onclick", "MulChkChanged(this)");
chkDivide.Attributes.Add("onclick", "DivChkChanged(this)");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  function DivChkChanged(x)
{
if(x.checked)
jQuery(document).bind('okbuttonpressed', DivVals);
else
jQuery(document).unbind('okbuttonpressed', DivVals);
}

function MulChkChanged(x)
{
if(x.checked)
jQuery(document).bind('okbuttonpressed', MulVals);
else
jQuery(document).unbind('okbuttonpressed', MulVals);
}

function AddChkChanged(x)
{
if(x.checked)
jQuery(document).bind('okbuttonpressed', AddVals);
else
jQuery(document).unbind('okbuttonpressed', AddVals);
}

Thats all ! Now if you run the page, you can see for yourself how the custom events work. Be sure to check any of the checkboxes, before brining up the modal popup to see calculated result. Thats all from me. Though this was a very simple example, the attempt was to illustrate how using ‘custom events’ can help in clean coding. Without them our javascript would have been inelegant and full of ‘if’ statements and global variables. Custom events are much more useful when dealing with more complex scenarios. They pave the way for better event driven programming in javascript.

Introduction To Web Development Using Javascript Templates

Screenshot of the application.

Download Files | View Live Demo

Javascript templates is upcoming technology for creating dynamic UI in web applications. The core of this technique is a javascript engine, that can generate HTML using a predefined template. In this article, we will see how to use open source TrimPath engine from Google Code website to create a basic application. It fetches images from Flickr’s public feed which match tags specified by the user, and displays their thumbnails along with other information.

What is a ‘javascript template’ ?

‘Javascript templates’ is one of the upcoming technology for use in Web 2.0. It relies on client side javascript, to generate, whole or part of a web page. This way, there is decoupling between data and the view (UI).Developing using javascript templates is very similar to designing reports. In classic web application, we rely on server side code to generate and send back the HTML. Using javascript templates, the server is relieved of this work. We will discuss the pros and cons of this technique in a bit detail, later in this article. I have created a simple diagram to illustrate what goes on in this type of applications.

How Javascript Templates work

About Flickr’s Public Feed

Before we start our application, let me tell you about Flickr’s public feed. Basically its an URL, which, when accessed, gives back list of images. The URL contains ‘tags’ for which we want so get images in the query string. It is possible to specify multiple tags separated by commas. This feed can be forced to return data in JSON format by specifying ‘format’ in the query string.

The feed URL with tags and output format specified as JSON:

1
http://api.flickr.com/services/feeds/photos\_public.gne?tags=mumbai&format=json 

The feed URL: The URL fetches results for tag ‘Mumbai’ and tells the service to give results in JSON format.

More information on using the feed can be found here: http://www.flickr.com/services/feeds/docs/photos_public/.

If you paste this URL in Firefox, you should see something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
jsonFlickrFeed({
"title": "Recent Uploads tagged mumbai",
"link": "http://www.flickr.com/photos/tags/mumbai/",
"description": "",
"modified": "2009-01-07T16:24:05Z",
"generator": "http://www.flickr.com/",
"items": \[
{
"title": "ABC",
"link":"http://www.flickr.com/....
"media":{"m":"http://farm4.static.flickr.com....
....
}\]})

As you must have realized,this is basically a call to Javascript function. The page which requested this data, is required to have a function with same name. This method of passing JSON data is called JSONP. We see this in more detail very soon.

Building basic ‘Search’ UI

1
2
3
4
5
6
7
<body>
<p>Tags:
<input id="txtTags" type="text" /><input id="btnSearch" type="button"
value="Search" onclick="return btnSearch\_onclick()" /><br /></p><hr />

<!--DIV serves as container to script tags !-->
<div id="srcDiv"></div>

Writing Javascript for our application

Our javascript is short and sweet. Every time the user enters some ‘tags’ and clicks ‘Search’ the ‘btnSearch_onclick’ function gets called and following things happen:

  • A new URL pointing to Flickr’s feed is constructed, which contains tags entered by the user.
  • A new script tag is created with the above URL as the value of ‘src’ attribute.
  • This script tag is dynamically inserted inside a placeholder, which triggers an AJAX request.

If you remember, ‘jsonFlickrFeed’ is name of callback function used by our feed. I have created a function with same name in javascript. This gets invoked automatically when , the AJAX call receives a response. The function contains only two lines of code which bind the data to our HTML template. In my page I have placeholder DIV with id ‘showphoto ‘, to display content.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script src="trimpath-template-1.0.38.js" type="text/javascript"></script>
<script type="text/javascript">
var myphotos;
function btnSearch\_onclick()
{
var tags = document.getElementById("txtTags").value;
var flickrURL = "http://api.flickr.com/services/feeds/photos\_public.gne?tags="+tags+"&format=json";
var container = document.getElementById("srcDiv");
var el = document.createElement("script");
el.setAttribute("src",flickrURL);
container.appendChild(el);
}

function jsonFlickrFeed(data)
{
var result = TrimPath.processDOMTemplate("photos", data);
document.getElementById("showphoto").innerHTML = result;
}
</script>

Creating a javascript template

The ‘trimpath-template engine’ (wired name..isnt it !) is a single javascript file. To use it we need to define a template inside our HTML page. Documentation of the template engine suggests that we use a hidden ‘textarea’ to host our template. Let us have a look at our template :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!--template code starts -->
<textarea id="photos" style="display:none">
<h1>${title}</h1>

{for i in items}
<span class="imgitem">

<div class="imgdiv">
<a href="${i.link}" >
<img src="${i.media.m}" style="border:0px" />
</a></div><br />
<span>
<span class="content"><strong>title:</strong>${i.title}</span><br />
<span class="content"><strong>author:</strong>${i.author}</span><br />
</span>
</span>

{/for}
</textarea>
<!--template code ends -->

<!--Container for HTML generated after binding to the template-->
<div id="showphoto" style="font-family:Calibri"></div>

For now, let us assume that we have a javascript object, which has been created from JSON returned by Flickr’s feed. Visit the feed URL (preferably in FireFox) and you should be able to see the ‘title’ and ‘items’ field. Inside each item there are more fields like ‘author’,’title’,’media’,’link’ etc. In the above template, text enclosed between curly braces ‘ { }’ are javascript statements. Those preceded by a ‘$’ sign, are expressions returning value. This is the convention followed by our template engine. The ‘${i.media.m}’ , points to URL of a thumbnail of an original image. By looking at the template it is clear, that we want to display a thumbnail, followed by title and name of the author of an image. I have used some CSS to make each item of same size (since sizes of thumbnails vary). Thats all to this application. With very few lines of javascript and HTML, we created a fairly useful application.

The Future

Javascript templates methodology is by no means going to completely substitute server side HTML generation. It has its own strengths and weaknesses. The major strengths are:

  • Separates UI from data.
  • Very easy to work with. Only knowledge of javascript and HTML required.
  • Since UI is generated at client, this eases load on server the a bit.
  • By combining this method with some powerful javascript libraries and things like REST, cool application can be created.

Now the drawbacks:

  • Requires javascript. Could be a problem for portable devices.
  • Designing AJAX based application is more painful than convention webapps.
  • Can’t bookmark !
  • Not search engine friendly.
  • Try pressing the ‘Back’ button on your browser ;-)

Hope you enjoyed this article. Please drop me a comment for any suggestions and criticism.

Simple 'Select-all' checkbox javascript for ASP.NET GridView, DataList, Repeater etc

One of the most common scenarios encountered in webpages is that of checkbox lists. I have seen many javascript implementations to handle selection/deselection of checkboxes in GridView like scenarios. In this article, I suggest yet another method to handle this scenario. Two big advantages of this method are:

  • No need to deal with “ClientIds” of ASP.NET controls. The javascript is independent of Ids of individual controls.
  • No extra code needs to added to ‘code-behind’ (*.aspx.cs). I mean absolutely no need for attaching javascript to individual checkboxes from code-behind.

In this article,I will illustrate the use of this method for checkbox column of a GridView. We will use jQuery javascript library for this, as future versions of Visual Studio are going to support it. So here we go: Firstly, add a ‘template column’ to a GridView. In the header and footer template we add a checkbox. Set the CSSClass of the checkbox in header and item template to ‘chkHeader’ and ‘chkItem’ , respectively. It is not necessary to define these styles.

Then, we add our javascript to the page. Be sure to include jQuery script file, before the script.

1
2
3
4
5
6
7
8
9
10
11
<script src="jquery-1.2.6.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(window).bind('load',function(){
var headerChk = $(".chkHeader input");
var itemChk = $(".chkItem input");
headerChk.bind("click",function(){
itemChk.each(function(){this.checked = headerChk\[0\].checked;})
});
itemChk.bind("click",function(){if($(this).checked==false)headerChk\[0\].checked =false;});
});
</script>

Now run the page.Selecting and deselecting the header checkbox should also change checkbox in each row. Deselecting checkbox from any row, should deselect the header checkbox. As, you must have realized you can apply similar technique for DataList, Repeaters and other such scenarios. Also this method is not ASP.NET specific, it should work for any scenario.

Adding multiple clientside event handlers to ASP.NET controls

I often come across scenario which requires assigning multiple javascript handlers to ASP.NET controls, via code. Let me elaborate the scenario:

  • You need to hook up multiple javascript handlers to some ASP.NET control (example, to ‘onclick’ event of a TextBox).
  • This has to be done from server side code (datagrid,datalist or any such dynamic scenario).
  • The javascript handlers are ‘functions’ that accept a number of parameters.

In this article, I will show how to do this with ‘jQuery’. As many of you might be knowing, there is talk of Visual Studio supporting jQuery in future. This makes ‘jQuery’ the ideal candidate. All one needs to do is download a javascript file from their site and reference it in the *.aspx page. I have written two javascript functions which I will demonstrate attaching to client-side ‘click’ event of ASP.NET textbox.

1
2
3
4
5
<script src="jquery-1.2.6.min.js" type="text/javascript"></script>
<script type="text/javascript">
function Handler1(p1){alert('Handler1 called.['+p1+']');}
function Handler2(p1,p2){alert('Handler2 called.['+p1+' '+p2+']');}
</script>

Now, in the code-behind of the *.aspx file, code looks like this:

protected override void OnPreRender(EventArgs e)
{
       StringBuilder sb = new StringBuilder();
       string functionCall = "$('#{0}').bind('{1}', function(){{ {2} }});\n"; 
       sb.Append(" $(window).bind('load',function(){\n");
       sb.Append(string.Format(functionCall,TextBox1.ClientID,"click","Handler1('param1')"));
       sb.Append(string.Format(functionCall string functionCall = "$('#{0}').bind('{1}', function(){{ {2} }});\n"; all, TextBox1.ClientID, "click", "Handler2('param1','param2')"));
       sb.Append(string.Format(functionCall, TextBox2.ClientID, "click", "Handler1('param1')"));
       sb.Append(string.Format(functionCall, TextBox2.ClientID, "click", "Handler2('param1','param2')"));
       sb.Append ("});");
       ClientScript.RegisterClientScriptBlock(this.GetType(),"ClickHandlers",sb.ToString(),true);
       base.OnPreRender(e);
}

The above code does two things:

  • Attaches a handler to the window.load event.
  • Adds handlers for client-side ‘click’ event of TextBox1 and TextBox2. This assignment is done inside body of ‘window.load’ handler.

Again to make things more clear, let us see what is being rendered on client-side:

1
2
3
4
5
6
7
8
9
  <script type="text/javascript">
//<!\[CDATA\[
$(window).bind('load',function(){
$('#TextBox1').bind('click', function(){ Handler1('param1') });
$('#TextBox1').bind('click', function(){ Handler2('param1','param2') });
$('#TextBox2').bind('click', function(){ Handler1('param1') });
$('#TextBox2').bind('click', function(){ Handler2('param1','param2') });
});//\]\]>
</script>

The ‘$()’ is the famous dollar function. The notation $(‘#TextBox1’) is roughly eqvivalent to saying document.getElementById(‘TextBox1’). To further understand the code check out tutorials for jQuery. As always, let me know your suggestions and comments.

Adding Subtitles to videos in Silverlight

Subtitles displayed on video

Click here to see online demo !

This article is about adding sutitles to videos hosted inside a Silverlight plugin. It is possible to do so using ultra-simple technique in javascript and a feature of Silverlight, which allows text to be drawn over videos. The technique involves a simple javascript timer, that checks the current position of video and shows appropriate subtitle text. With this tecnhique you can:

  • Add subtitles to any video.
  • Customize how they look (color,font, positon).
  • Add subtitles in multiple languages.
  • Make use of javascript and silverlight.So the whole job can be accomplished with a text editor.

Given below is detailed ‘how-to’.

Creating the XAML

1
2
3
4
5
6
7
8
9
10
11
12
13
<Canvas Width="320" Height="240" xmlns="http://schemas.microsoft.com/client/2007"  
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="Black">

<MediaElement x:Name="VideoControl" Canvas.Top="0" Canvas.Left="0"
Source="http://localhost/SlvrSub/test.wmv" AutoPlay="true"> </MediaElement>

<Canvas Background="#40000000" Width="320" Height="20" Canvas.Top="220"
Canvas.Left="0" Opacity="255"> <TextBlock FontSize="12" x:Name="Subtitle"
FontFamily="Arial Unicode MS" Canvas.Left="40" Foreground="White">
Javascript needs to be turned on to show subtitles.</TextBlock>
</Canvas>

</Canvas>

In the above XAML notice the following things:

  • The size of parent ‘Canvas’ is set to size of video( i.e 320*240).
  • There is a child ‘Canvas’ that contains a TextBlock, which is used to show the subtitles. Note that I have used a unicode font for displaying subtitles, so that multiple languages can be supported.
  • Videos should be converted to a format playable by Silverlight.

Writing Javascript

The javascript required for this, is very simple. I have written a simple javascript class, called ‘Subtitler’ which is used to fetch subtitle related to current position of the video. The current position of video is obtained using ‘MediaElement.Position.seconds’. One nice thing about this is, it returns total number of seconds from the start of the video. This means we dont have to mess around with a ‘Timespan’ object get current position. Subtitles are stored as javascript array. The index corresponds to the position (in second) where it should be shown in the video. I mean ‘subtitle[120]’ would be shown during the 120th second of the playback. To make things clearer, let use see the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var sub_en = new Array();
sub_en[1] = "Subtitle as 1st Second";
sub_en[2] = "Subtitle as 2nd Second";
sub_en[3] = "Subtitle as 3rd Second";
sub_en[4] = "Subtitle as 4th Second";
sub_en[5] = "Subtitle as 5th Second";
// ..... Add till last second of video.

var slvr_ctrl,videoCtrl,subobj;
var persistTextSec = 5;
var oldTitlePos = 0;

//Initialize variables. Called on 'OnInit'
// of Silverlight Plugin.
function Init(sender)
{
subobj = new SubTitler();
subobj.SubtitleDataSource = sub_en;
slvr_ctrl = sender.getHost();
videoCtrl = slvr_ctrl.content.findName("VideoControl")
//Set a javascriptimer
window.setTimeout("timerCompleted()",100);
}

//If the video is playing get subtitles corresponding to current
// position of the video.
function timerCompleted()
{
if(videoCtrl.CurrentState == 'Playing' || videoCtrl.CurrentState == 'Opening')
{
var sec = Math.round(videoCtrl.Position.seconds);
var lbl = slvr_ctrl.content.findName("Subtitle");
var subtxt = subobj.GetSubtitle(sec);
if(subtxt)
{lbl.Text = subtxt; oldTitlePos = sec;}
else
{ if(sec - oldTitlePos > persistTextSec) lbl.Text = "";}
}
window.setTimeout("timerCompleted()",100);
}

//Error handler
function Err(a,z)
{alert(z.errorCode+" "+z.errorMessage);}

The ‘Init’ function get called when the plugin loads. It initializes global variables and sets off a javascript timer. Though the timer is triggered every 100 millisecond, subtitles can only be changed per second. When the timer elapses ‘timerCompleted’ is called. It simply pulls out the subtitle corresponding to current position (in seconds) of the video and draws it on top of the video. Since we care of showing subtitles with only second accurracy, we round off the current position of video and get the corresponding subtitle text (since it turns out to be a floating point number). The ‘persistTextSec’ value is number of seconds a subtitle should continue to show on the screen, if no subtitles are found for consequtive seconds. If you want to simply test subtitling for long video, then you can use a javascript loop to initialize subtitle array to dummy strings

1
2
3
//Intializes subtitles with dummy strings
//for first hundred seconds of playback.
for(i=0;i<100;i++) {sub_en[i]="Subtitle at" +="" i;}="">

Creating HTML file

The HTML file is a very straightforward one. It includes ‘Subtitler.js’ (for the Subtitler) and ‘Subtitles.js’ (containing subtitles). The sequence of inclusion of these scripts is important. Then, all that is required is the code to embbed the Silverlight plugin itself.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head><title>Subtitles Demo</title>
<script type="text/javascript" src="Subtitler.js"></script>
<script type="text/javascript" src="Subtitles.js"></script>
</head>
<body>
<object type="application/x-silverlight" height=240 width=320>
<param NAME="Source" VALUE="VideoPlayer.xaml">
<param NAME="MaxFramerate" VALUE="30">
<param NAME="Windowless" VALUE="0">
<param NAME="OnError" VALUE="Err">
<param NAME="OnLoad" VALUE="Init">
</object>
</body></html>

That was easy wasn’t it. If you use this technique in your please share it with me so that I can put a link here on my website. As always appreciation or criticsm are always welcomed.

Silverlight Video Subtitles Demo


Current Position:
Select Subtitle Language: English  Marathi   Hindi

You might realize the problem with rendering of Indian script. Please read this post to know more about the cause : Silverlight and Indic Script Rendering

Click here to read how it was created.

This a multi-lingual subtitle demo. I have kept a really short video, because of bandwidth constraints. You can change the subtitle language even when the video is playing. The subtitles are given below. There seems to be problem with Silverlight rendering joined Devanagiri letters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
	
var sub_en = new Array();
sub_en[1] = "That's my Iron";
sub_en[6] = "My battrey charger";
sub_en[10] = "The Spore Creature Creator !";
sub_en[16] = "Some coins.";
sub_en[19] = "That's it !";
 
var sub_hi = new Array();
sub_hi[1] = "वह मेरा लोहा है";
sub_hi[6] = "मेरा बैट्रे चार्जर";
sub_hi[10] = "बीजाणु प्राणी निर्माता!";
sub_hi[16] = "कुछ सिक्के।";
sub_hi[19] = "बस !";
 
var sub_mr = new Array();
sub_mr [1] = "तो माझा लोह आहे";
sub_mr [6] = "माझे बॅटरी चार्जर";
sub_mr [10] = "बीजाणु प्राणी निर्माता!";
sub_mr [16] = "काही नाणी.";
sub_mr [1 9] = "बस!";

Ashish's Image Resize utility

This is a simple console utility written in C# that can :

  • Bulk resize images.
  • Add borders to images.
  • Add watermark text to images (such as copyright notice).
  • Save output images in particular image format.
  • Adjust color and width of border .
  • Control color,opacity,font,size of the watermark text for a batch.

This utility was written in C# (.NET 2.0) and is only available for Windows operating system. It uses “System.Drawing” to accomplish it’s work. The program processes all the files in a directory. Errors are logged in an log file. Detailed information regarding usage can be found in the manual of the program. I mainly created this program to process images from my digital camera, for uploading to the web or emailing. If you find it useful, please write a comment. Suggestions are also welcomed. Below is a processed image sample

Before downloading

THIS SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTIES OF ANY KIND. THE AUTHOR IS IN NO WAY RESPONSIBLE FOR ANY DAMAGE CAUSED BY INSTALLATION AND/OR USE OF THIS SOFTWARE. THIS SOFTWARE IS EXPERIMENTAL WORK AND NOT THROUGHLY TESTED. USE IT AT YOUR OWN RISK.

Download the program (Alfa release): imgresz.zip
Download .NET framework (only if you don’t have it) : .NET Runtime v2.x