Google
Web Netomatix

How to send data from Javascript on page to Silverlight control

by Admin 1. August 2009 05:08

Download Demo Project

I have been discussing use of jQuery to send AJAX request to server to get some data every X number of seconds to get server time and calculate some latency numbers. Now it is time to add some color to it. The numbers that I am getting is great and provide some useful information. But having a visual of how these numbers are varying with time will enhance utility of these statistics. So I decided to add some charts to show these latency numbers are varying with time. In this article I am going to show how you can pass the data obtained from server using AJAX request to a Silverlight application hosted on the page. This silverlight application uses charting control from Silverlight toolkit. Lets see how all this fits together to get this to work.

Bridge between Javascript and Silverlight component

In one of earlier posts, How to setup communication between silverlight applications, I discussed how you set this bridge up. The sample project for that article was done using Silverlight 2. The mechanism to set up the communication bridge has not changed in Silverlight 3. So all those concepts still apply for this project as well. The following code snippets shows declaration of a method decorated with ScriptableMember attribute to let silverlight framework know that this methos is to be exposed to javascript. And in constructor of the page, HtmlPage.RegisterScriptableObject method is called to register the class to be exposed to javascript. I do not want to expose all my properties, fields and methods to javascript. So I have not added scriptable attribute on class itself. I want to control what is exposed and what is not.


public MainPage()
{
	InitializeComponent();
	HtmlPage.RegisterScriptableObject("ClockDataClient", this);
	SetupChartDisplay();
}
		
[ScriptableMember]
public void PutNewClockData(string xtx, string data)
{
	AddDataPointToPlot(data);
}

This completes what needed to be done from silverlight application to expose its end points to javascript. Now we are going to see what is done on pages to communicate to silverlight control.

Setting up the page

First thing you need on the page is to include your Silverlight control. On Default.aspx you will find the following declaration of object tag that will host the control.


<object id="clockDisplayPlugin" data="data:application/x-silverlight-2," 
  type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/ClockLatency.xap"/>
<param name="onError" value="onSilverlightError" />
<param name="onLoad" value="onLoadClockDisplay" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="3.0.40624.0" />
<param name="autoUpgrade" value="true" />
<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
  <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="" style="border-style:none"/>
</a>
</object>

All this code was generated by wizard when I added test paste to my project. I added a new param declaration to handle load event. This event is fired when Silverlight control has been loaded. On lets see what all javascript is required to send message to silverlight control.


function onLoadClockDisplay(sender, args) {
 objClockDisplay = sender.getHost();
}

function sendLatencyData(data) {
 if (null != objClockDisplay) {
  objClockDisplay.Content.ClockDataClient.PutNewClockData("", data);
 }
}

As you can see, in load event handler I saved the reference to Silverlight control object. Then from my ajax request code, every time I got the data from server, I call sendLatencyData method. This method calls PutNewClockData method that I exposed from control using ScriptableMember attribute. This call constitutes of four parts.

objClockDisplay.Content.ClockDataClient.PutNewClockData

objClockDisplay is reference to our silverlight plugin. Content is the property on plug-in object through which control's methods are exposed. ClockDataClient is the key that was used to register the class as scriptable in our control. PutNewClockData is the name of the method.

Setting up charting control in Silverlight component

I used charting control from Silverlight Toolkit for my project. I decided to use column chart to display latency numbers over time. In silverlight application project, I added the following XAML on MainPage.


<chartingToolkit:Chart Title="Clock Latency" x:Name="latencyChart" BorderThickness="2">
 <chartingToolkit:Chart.Series>
  <chartingToolkit:ColumnSeries Title="Latency" DependentValueBinding="{Binding Latency}" AnimationSequence="Simultaneous" />
 </chartingToolkit:Chart.Series>
</chartingToolkit:Chart>

In code behind i created a collection to save data sent from javascript and attached the column series to that collection. I only keep last 11 entries in the collection.


void SetupChartDisplay()
{
 ColumnSeries cs = latencyChart.Series[0] as ColumnSeries;
 foreach(var lItem in cs.LegendItems)
 {
  lItem.Visibility = System.Windows.Visibility.Collapsed;
 }

 latencyChart.Width = 500;
 (latencyChart.Series[0] as DataPointSeries).ItemsSource = DynamicCollectionItemsSource;
}

You can see it was pretty simple to set this whole up and get javascript to send data to silverlight control and render the charts using those numbers.

Click to see demo

Views: 1350

Tags: , , ,

JavaScript | JQuery | Silverlight

Insert new elements in reverse order using jQuery

by Admin 28. July 2009 06:28

prepend enries using jquery

I have been extending the current sample clock synchronization application to add some more features to show more capabilities of jQuery. In the last update I added functionality to display latency numbers when service was called every X number of minutes. If you will let the page running for quite some time you will see how quickly the entries get appended to the display. What we really want is that latest entries should be displayed at the top. So basically instead of appending the new entries, we want to prepend the new entry to the last entry added. We are in luck here. jQuery does offer couple of methods here that makes it easy. prepend, prependTo, before, insertBefore methods are your friend here. It turns out that all these methods get mapped to one function behind the scene, insertBefore. Following code snippet from the application shows entries are added in reverse order.


var elLastLatencyEntry;
var elLastMessageEntry;

function displayLatency() {
 var elToAppend = null;
 if (latency == -1) { elToAppend = $("<p>Initializing</p>"); }
 else { elToAppend = $("<p>" + latency + " ms</p>"); }
 if (null == elLastLatencyEntry)
 { elLastLatencyEntry = elToAppend.appendTo(elLatencyDisplay); }
 else { elLastLatencyEntry = elToAppend.prependTo(elLastLatencyEntry); }
}

You can see from the code that I save the last entry that was added in a variable for later use. This avoids over head of finding the latest entry again and again every X number of seconds.

Views: 1058

Tags: , ,

AJAX | JavaScript | JQuery

How to modify default behavior of getJSON or other jQuery AJAX requests

by Admin 24. July 2009 08:14

In my previous posts How to serialize AJAX requests and others, I have been using simple jQuery method .getJSON to get response from server. You can see that this method takes only 3 parameters and there is not much you have to set or do to set up your AJAX calls and it works for 90% of the cases. But some time you run into situation where you need little bit more control on how the request is set up or want to control the request a little bit. jQuery does provide you excess to underlying structures to set some parameters for the calls or you can use the low level .ajax. A lot of time you really are not looking to use .ajax function but you want to set some default behavior for all the AJAX requests that are being send using .getJSON. To do that you can use .ajaxSetup method. This function has one parameter where you can set up all the AJAX call parameters in a structure. For example in my application, I want to make sure that all AJAX calls time out in 10 second and I also want that all errors should be taken care of in one function. So I called .ajaxSetup method at load time to set up the behavior.


$(function() {
$.ajaxSetup({
 timeout : 10000,
 error: errorDisplay,
 sync: true
});
elClockDisplay = $('#clockDisplay');
elLatencyDisplay = $('#latencyDisplay');
elUpdatesPanel = $('#siteUpdatesPanel');
getServerTime();
}); 

There are lot of other properties that you can set in this structure. I will recommend reading jQuery for latest information about these properties. I will list some of the common ones that you may run into.

  • type
  • beforeSend
  • timeout
  • processData
  • dataTyoe

Views: 1432

Tags: , ,

AJAX | JavaScript | JQuery

How to set cache control headers for AJAX request response

by Admin 22. July 2009 03:03

I have been developing AJAX enabled applications before the term AJAX was coined. I have been doing it for so long that some of things that I do come kind of naturally. And one of the things that I always do is to make sure that response is not cached to ensure that client is never working on stale response even though it sent new request every few seconds. So I have a small piece of code that I pretty much use in all applications that sets some headers.


Response.ContentType = "text/plain";
Response.Expires = -1;
Response.CacheControl = "no-cache";

These are not just the only headers but gives you an idea how cache was being control. I never ran into any trouble with any applications till last week when I was told that our application is filling up Temporary Internet Files folder of the users. This was the first time ever I was reported such issue and actually this was first time I observed this behavior in my applications. So I fired up Fiddler to see whats going on with my requests. I looked at the response headers and saw the following.

First, I was not expecting to see Cache-Control: private. So that was little out of whack. Second, the expiration time was correct because I always set to an hour behind the response time to make sure that it is stale for caching. I have been using the same caching utility routine for so long that I did not suspect that something is wrong there. Then I looked inside Temporary Internet Files folder again and noticed that this was the only request that was being saved in the folder, others were not. So I looked at the implementation and found that the server side implementation for this request was not using my standard utility to set cache headers. Following is the code snippet that I ad in place. Well why i changed the implementation for this particular call is whole different story.


Response.ContentType = "text/plain";
Response.Expires = -1;

Notice that it is missing Cache-control : no-cache header. That explained everything. After I added this header, everything went back to normal. So I decided to do some experiment to observe behavior of setting different headers.

No Cache-control: no-cache header on any call

You will notice that from my earlier post How to serialize multiple AJAX calls in jQuery, I have two AJAX calls being made. And you can see from snapshot above that both are being saved in Temporary Internet File folder.

Cache-control: no-cache header set on one request only

Now you can see that only one request is being saved in the folder and other has disappeared.

Cache-Control:no-cache header set on all requests

Well, there is nothing to show here in Temporary Internet Files folder because nothing is being saved there any more. But here is the snapshot of response headers as seen in Fiddler.

Now you can see that no-cache header and pragma has been set correctly.

Set cache-control header correctly

As more and more applications are using AJAX or Web2.0 style of implementations, if you do not set these cache control headers correctly, you will see that browser cache folders will accumulate lot of entries. It is not that big of a deal as far as application working goes because this temporary cache will not grow beyond specified limits for a particular browser. But it will hurt performance of other internet sites that you visit because their content will not be found in cache and will have to reloaded from server again. Other performance hit you will take is that now browser has to spend an extra CPU cycle to save these entries on the disk.

Views: 1604

Tags: , , , , ,

AJAX | ASP.Net | JavaScript | JQuery

How to format and update GridView and DataGrid rows using JQuery

by Admin 14. July 2009 14:21
datagrid using jquery

Download Sample Project

This is based on a question asked by one of my blog readers.

I have 2 datagrids. Each Grid has the same amount of columns and each grid has a select column as the last column on the right added from the "gridview/ edit Columns/ CommandField/ Add" sequence. The first GridView has the Select column as a Link The second GridView has the select Column as a button I want to be able to change the text for both the Link and button in cell(4), setting them to the value in cell(1) from the same row using the GridView_RowDataBound event. However, using "cell(4).text = cell(1).text" just overwrites the text value removing the hyperlink and button.

The behavior described in this question is as expected. When you set text of a cell in grid, it directly affects HTML that is going to be rendered. When you set text value of a cell, it means that you are setting innerText of the cell. The column that GridView creates for command fields (Edit, Delete and Select) are a (anchor) or button elements. So you can see what will happen if you set text value in that cell. It will wipe out those link or button controls and replace them with simple text string.

There are properties like EditText, DeleteText and SelectText for CommandField column in grid view. If you try to set these values using a server side method by passing it DataContainer object, you will get following exception thrown.


Databinding expressions are only supported on objects that have a DataBinding event. 
System.Web.UI.WebControls.CommandField does not have a DataBinding event.

After looking at the requirements, i realized that requirements are as simple as replacing text with value from another cell in the same row. There is no need for doing any server side tricks or things like that. I can simple put together a simple client side java script that will take values from cell 1 and put them in whatever cell I want. Abd I came up with this small javascript solution using jQuery. This small code snippet shows how you can manipulate GridView or DataGrid on client side using jQuery. Let me show you the client side javascript that I added on the page. Then I will explain what this code is doing.


<script type="text/javascript">
function updateCommandLinks() {
 var $gridTable = $('#productsGrid');
 var rows = $gridTable.find('tbody > tr');
 var slicedRows = rows.slice(1, rows.length - 2);
 slicedRows.each(function() {
  var cells = $(this).find('td');
  var cellElem1 = cells.get(1);
  var cellElem5 = cells.get(5);
  $(cellElem5).find('a').each(function() {
   $(this).addClass('commandlink').append(" " + cellElem1.innerText);
  });
 });
}

$(document).ready(function() {
  updateCommandLinks();
});
</script>

The above code may look little verbose considering you can write very concise code using jQuery. But for sale of explaining and debugging, I decided to make it little bit verbose. I am sure you can reduce it to half the lines of code that I have written.

The implementation adds a handler for document load event. In that event handler here are the steps it follows:

  1. Finds the element that has id of productsGrid. In our case, that is HTML element ID of our grid view.
  2. In the table, it gets collection of all the rows, identified by tr tag.
  3. Since in my implementation I have header and pager, that adds three rows into the collection. One top row for the header and then the last row itself will contain another table that contains a row for paging elements. To keep it simple, I decided to use slice function to remove first and last 2 rows from collection. You will need to modify this implementation depending on your grid rendering.
  4. It iterates over each row in the collection.
  5. For each row it then finds all cells, identified by td tag.
  6. In my case, I want to replace text in command links with text from second column. So I saved reference to cell at index 1 by using get function.
  7. Then I extracted all elements with tag a from sixth column.
  8. Then it iterates over collection of anchor a tags and appends text from second cell to text in each of the links.

I think that is a simple implementation that serves the purpose without making any changes on the server side. The attached project has the complete implementation for this grid. This is a Visual Studio 2010 project. But you should be able to copy the script from the page to your implementation.

Views: 6627

Tags: , , , ,

ASP.Net | DataGrid | GridView | JQuery | JavaScript