How to implement OWA style new message notifier poup using Silverlight and javascript

by Viper 6. October 2009 14:06
OWA style new message notification popup

Download Demo Projects

This is one of the projects I have been planning to work on for some time. I was looking into building an event notifier in one of my ASP.Net application. I wanted it to be more like Outlook Web Access (OWA) new email notifier pop-up. It is the one that slides up from bottom right corner of your browser when there is a new email in your inbox. I had built it in the past using all javascript solution. Yes, this Microsoft is one of the earliest implementation of so called AJAX applications. I did not want to deal with all the javascript code related to setting up HTTP calls and then dealing with response and rendering the results.

I wanted to leverage Silverlight to do all the heavy lifting. And use light weight javascript implementation on client to do animated sliding and positioning of the popup notifier box. At the end it turned out be quite an elegant solution that worked on major browsers like Internet Explorer, FireFox and Chrome. This article is an attempt to describe How to implement OWA style new email notifier popup using Silverlight and Javascript.

The implementation involved the following technologies and I will describe how each component was implemented

  • ASP.Net web application
  • ASP.Net web service
  • Silverlight application

ASP.Net Web Service

Let's start with discussion of the component that is responsible for communication of data between client and server application. The client requests data from server at certain frequency to check if there are any new messages. So I implemented as simple ASP.Net web service application with few web methods. For this demo I had a simple method with following signature.


[WebMethod]
public string GetGlobalMessages()
{
 List msgs = MockData.GetGlobalMessages();
 return msgs.ToJson();
}

For demo application, I implemented a MockData class that creates a random list of messages and then serializes that collection as JSON and sends it in response. I implemented ToJson as an extension method on List<StatusMessage> object. You will find it in Extension.cs file in ActivityData project.


public static string ToJson(this List<StatusMessage> msgs)
{
 var ser = new DataContractJsonSerializer(msgs.GetType());
 var ms = new MemoryStream();
 ser.WriteObject(ms, msgs);
 var serializedData = System.Text.UTF8Encoding.UTF8.GetString(ms.ToArray());
 return serializedData;
}

You can see there is nothing fancy about this whole implementation to make it work with a Silverlight client. A very simple ASP.Net web service.

Silverlight Application

This is where all the action happens. There are few components of this application, rendering and data access. Lets us first discuss data access. The client application is to talk to server at certain frequency. That means I need some kind of timer going in the application. When this timer ticks at specified interval of time, it send asynchronous request to server to get new messages. I have implemented this whole mechanism in MessageMonitor application. When this class is constructed, it creates an instance of DispatchTimer. You may be asking why DispatchTimer and why not simple Timer application. The problem is that when you are dealing with user interface application, you can only update the controls on the thread on which they were dispatched. Regular timer does not executes on that dispatcher thread. So if you will try to update your user interface on that thread you will get exception complaining about cross threaded access. Here is the code that created DispatcherTimer for my application.


private void CreateMessagePollTimer()
{
 _messagePollTimer = new DispatcherTimer();
 _messagePollTimer.Tick += new EventHandler(MessagePollTimer_Tick);
 _messagePollTimer.Interval = new TimeSpan(0, 0, MessagePollInterval);
}

When the timer ticks it calls MessagePollTimer_Tick method. And that method makes async request to server to get new messages.


void MessagePollTimer_Tick(object sender, EventArgs e)
{
 if (Stopping || MessagePollInProgress) return;
 GetMessages();
}

When async request to server completes, the following method gets called. You can see that now it uses the same JsonSerializer class to de-serialize the response into list of StatusMessage objects. And then it raises event for objects that have subscribed to the event.


void GetGlobalMessagesCompleted(object sender, 
  SiteMessagePanel.ActivityDataServices.GetGlobalMessagesCompletedEventArgs e)
{
if (e.Error != null)
{
 return;
}
 var msgsData = e.Result as String;
 var msgs = msgsData.FromJson();
 System.Diagnostics.Debug.WriteLine(msgs);
 StatusMessageEventArgs args = new StatusMessageEventArgs(msgs);
 OnStatusMessageReceieved(args);
}

Page class that implements user interface for popup, handles this event and renders all the messages.


void Monitor_StatusMessageReceieved(object sender, 
 ByteBlocks.ActivityData.StatusMessageEventArgs arg)
{
 if (arg.Messages.Count == 0)
 {
 msgTextBlock.Text = "No messages received";
 ShowClientPanel(false);
 return;
 }

 msgTextBlock.Text = string.Empty;
 messagesPanel.Children.Clear();
 foreach (var msg in arg.Messages)
 {
  StackPanel sp = new StackPanel();
  TextBlock tb = new TextBlock();
  tb.Text = msg.Title;
  tb.TextWrapping = TextWrapping.Wrap;
  sp.Children.Add(tb);
  messagesPanel.Children.Add(sp);
 }
 ShowClientPanel(true);
}

ASP.Net application and javascript

ASP.Net application acts as a host for the silverlight control that I created to render messages. I have implemented a simple Server Control that hosts it. Then I added that control inside a simple div on the master page. And I have very simple vanilla implementation of the server control. It does not have very complicated implementation. I simply copied the code generated by silverlight wizard for test page into that control


<div id="statusslideup">
<ByteBlocks:StatusPanel runat="server" id="statusPanel" />
</div>

Calling Javascript Method From Silverlight

So far we have implemented two pieces of the application that drive the data and render it. Now comes the fun part. How are we going to trigger the client to show the popup and animate it to come up from bottom. First, it is Silverlight application that is running the timer. So it is the one that has to trigger the client. I implemented some java script code that shows the DIV that hosts silverlight client component. And then small piece of code that implements animation. Silverlight framework provides a very simple mechanism to invoke any Javascript method that is implemented on client side. I implemented a very simple method in silvelight application to call my JS method whenever there are new messages for the user.


private void ShowClientPanel(bool show)
{
 HtmlPage.Window.Invoke("_showStatusPanel", show);
}

It could not be any simpler. And the following Javascript function implements small piece of code that calculates position of popup notifier window based on browser height and height of element containing silverlight control.


setStatusPanelPosition = function() {
 if (_statusdiv) {
 _maxPanelPos = document.body.scrollTop + ($(document).height() - _statusdiv.clientHeight);
 _curPanelPos = $(document).height();
 if (!_isStatusVisible) {
  _sliderInterval = setInterval("_slidePanel()", 5);
 }
 else {
  _statusdiv.style.top = _maxPanelPos + "px";
 }
 _isStatusVisible = true;
 }
}

Demo Project

Attached demo project is a collection of Visual Studio 2010 projects and solution. If you do not have VS2010, you can simply create a new solution and projects in VS2008 and copy the source files in there. You are also going to need to download Silverlight 3 Toolkit because I use theming controls from that toolkit to give some zing to the UI.

I hope this demo project helps you in building cooler implementations of OWA like message and event notifier windows.

Views: 4417

Tags: , ,

ASP.Net | Javascript | JQuery | Silverlight

how to insert new elements on page in reverse order using jQuery

by Viper 28. July 2009 06:35

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: 2721

Tags: , ,

AJAX | Javascript | JQuery

Difference between AddEventListener and Attachevent javascript function

by Viper 24. June 2009 06:06

Even after so many years of javascript development, I hit my head into wall yesterday. I had some piece of code that needed to be executed on window load event. So being cross browser support freak, I had a check for addEventListener and attachEvent to makes sure that most of the browsers were covered. Yes, you must be thinking why i am not using libraries like jQuery. Simple answer is that in this release of the application I could not because of additional testing required. Following code should be something we all have seen at some point.


if (window.addEventListener){
  window.addEventListener('load', doWindowLoadVoodoo, false); 
} else if (window.attachEvent){
  window.attachEvent('onload', doWindowLoadVoodoo);
}

All of a sudden the application stopped working on >FireFox. As far I remembered i did not make any substantial changes to java script or any server side. After banging my head for some time, I decided to look at where I defined the above piece of code. On first look nothing looked out of place. When I looked closely, I was beating myself. Look at the code below.


if (window.addEventListener){
  window.addEventListener('onload', doWindowLoadVoodoo, false); 
} else if (window.attachEvent){
  window.attachEvent('onload', doWindowLoadVoodoo);
}

If you have not noticed, I modified the line of code that was attaching to load event using addEventListener. The correct syntax is to simply specify name of the event and not the event handler name. So in this case, event is load and not onload. Where as attachEvent requires you to specify event handler name which in this case is onload. This is very subtle mistake that one can make.

Views: 2095

Tags:

Javascript

Add Remove HTML Elements Dynamically With Javascript Using JQuery

by Viper 16. March 2009 02:32

I was experimenting with some internals of JQuery while writing some simple one or two liner scripts to see how JQuery works. Like any programming language, we all start with a Hello world. So here is my Hello World example using JQuery.


<body>
 <form id="form1" runat="server">
  <div id="content">
  <script type="text/javascript">
  $(function() {
   var v = $("<p>Hello World</p>");
   v.insertAfter("#content");
   });
    
   </script>
   </div>
</form>
</body>

This simple piece of code is inserting a new paragraph HTML element dynamically into document. Translation of the script block is as below:

  • JQuery creates a new paragrah HTML element. If you look at the variable returned by first like of code, it looks as below. You can there is HTMLParagraphElement which is DOM element representing p tag.
  • Next line of code tells jQuery to insert newly created paragraph element after an element that has id of content. JQuery finds that element using well known getElementById and calls DOM method to insert new element dynamically after element with id content.

Simple, isn't it. I will write how this simple piece of code works internally in next post.

Views: 1665

Tags: ,

Javascript | JQuery

What JQuery File To Use

by Viper 15. March 2009 17:36

When you go to download JQuery files from the site, you are presented with 3 files that you can download.

  1. JQuery-1.3.2.js
  2. JQuery-1.3.2-vsdoc.js
  3. jquery-1.3.2.min.js

Then you start thinking which one to download use. As far the features or functionality goes, all three files do the same job. The difference is what extra help these 3 files provide.

Lets look at jquery-1.3.2.min.js. If you open this file in editor, you will find that the whole implementation is very cryptic and is presented 2 lines. Well as name suggests, this file has been minified. What this means is that all indentation, line breaks, indentations have been removed. And all function parameter names have also been turned into very short names. This helps in keeping the file size small. You shall be using this file when you deploy your application in production environment.

Next is JQuery-1.3.2.js. If you will open this file, you will notice that all functions and implementation is nicely formatted. And all function and parameter names are very self explanatory and may be long at times. This definitely bloats the size of the file. But this file is very helpful during development stage or for debugging purposes because you can clearly see where the error is what could be cause of the error.

Last one is JQuery-1.3.2-vsdoc.js. Open this file and you will find that each function and parameter has been nicely documented using Visual Studion XML Doc conventions. What this means is that Visual STudio provides nice intellisense support for JQuery implementation. You can see from following screen shot how help documentation pops up when you start writing JQuery code in your page's editor.

When you are developing your web application, you should always use this file in development stage and take advantage of Visual Studio's intellisense. Since Microsoft has adopted JQuery in its MVC framework, I am expecting that Microsoft will contribute to JQuery to add more features and build some tools around to it to help development of ASP.Net application easy using JQuery.

Views: 776

Tags: ,

Javascript | JQuery

Not able to debug javascript syntax error

by Viper 18. January 2009 13:36

I was working on a Facebook application. I made some changes to the page as well as javascript controlling behavior of the page. Fires up the application and I kept getting javascript error dialog popup. And everytime I will hit "Yes" to allow debugging of error, the code will not goto debugger and will move on. I tried Firebig, IE Developer toolbar etc. Nothing will show me the error. Then I started going back to all changes that I checked. Right on the HTML markup i noticed that I added a call to a javascript function on a click event. And noticed that I missed closing quotes on a javascript function call for a click event. After I added closing quotes error went away.

So if you run into situation like this, do look at javascript syntax in mark up as well. Thats where the problem may be. For all javascript file syntax errors, tools like firebug etc. can point you to right location most of the time.

Views: 715

Tags:

Javascript

Powered by BlogEngine.NET 1.5.1.7
Theme by Naveen Kohli