Wednesday, July 23, 2008

insertAdjacentElement for FireFox

There is a JavaScript method called insertAdjacentElement() that only works in Internet Explorer (IE) and it is NOT supported in FireFox. There is an alternative however. Here is how you could use insertAdjacentElement() to insert a newly created element to the right of a specified element that already exists on the page: var newElem = document.createElement("span"); newElem.innerHTML = 'this is a new element here'; existingElement.insertAdjacentElement("AfterEnd", newElem); If you are want your code to work in IE and FireFox, try replacing the last line with: srcElement.parentNode.insertBefore(newElem, existingElement.nextSibling); If the browser you are using doesn't support that, you can try replacing the last line with the following (it is the same sometimes, but sometimes not) existingElement.parentNode.appendChild(newElem);

Tuesday, July 22, 2008

Adding a loading animation to your AJAX requests

I think AJAX is great. It can be a little confusing for the user if the response is not immediate though. In cases like these it is nice to give the user some feedback so that they know that something is happening and when it is done. I like to a little spinning wheel or something to indicate this condition. You can easily add this to most requests that are AJAX based with only a few lines of code.

// register the event listeners so we will receive the events 
//when they are fired by the AJAX.NET framework
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(BeginRequest);

function BeginRequest(sender, args) {
  // srcElement is the object that invoked the AJAX call. For example, maybe a textfield
  var srcElement = args.get_postBackElement();
 
  // the path should point to a nice animated gif.
  srcElement.style.backgroundImage = 'url(images/loading.gif)';
  srcElement.style.backgroundRepeat = "no-repeat";
  srcElement.style.backgroundPosition = "right";
}

You can use what ever image you want for the animation. I like this one from the AJAX toolkit. It is from the DynamicPopulate Demo

Start or Stop MS SQL Server using a shortcut

If you are like me you don't always develop against SQL Server on you local computer. Most of the time I use one of the servers in the office. I never seem to have enough memory, so I don't have the MS SQL Server service launch on startup. This saves memory for other things I am doing. However, when I want to start MS SQL Server, I hate navigating and starting it manually. I figured out that I can start it just by double-clicking a windows shortcut and that is really nice. I don't recommend making a shortcut that points to the sqlserver.exe, instead I recommend creating a shortcut that just starts the windows service. This way it is fully accessible, and works the way it was meant to. Here is what you do.
  1. Create a new shortcut.
  2. When it asks you to browse or specify the location of what you want the shortcut to point to, enter the following: cmd /c net start MSSQLSERVER
  3. Click next, and call the shortcut whatever you want.

Click finish, and that is it. Now you can start MS SQL Server manually, but with the click of an icon. You can stop it the same way, just use the following command: cmd /c net stop MSSQLSERVER

Monday, July 21, 2008

Understand AJAX Client Side Events

I found this example in the AJAX.NET documentation, and it is very helpful for understanding how javascript events work and when they fire. To figure see the events firing on your own AJAX enabled page do the following.
  1. Create a new javascript file in your Visual Studio Web Site.
  2. Copy the javascript code below into a .js file and call it what ever you like. In this example I'll call it AjaxEvents.js.
  3. Add the following line in blue to your script manager that already exists on your page <asp:scriptmanager id="ScriptManager1" runat="server"> <span style="color: rgb(0, 0, 153); font-weight: bold;"> <scripts><asp:scriptreference path="AjaxEvents.js">/asp:scriptreference></scripts> </asp:scriptmanager>
  4. Add the following HTML somewhere on your page. It will be used to append debug text as the events fire. <span id="ClientEvents"></span></span>
Now you can do what ever you usually do to make your AJAX code execute, but this time you will see the JavaScript events that are firing. You can now add cool things to the client side when these events occur. Some ideas are display animations when AJAX is running, progress messages, disabling or enabling page elements. The possibilities are great. Obviously, you will want to remove the debugging code and probably the span tag since all this is just to show you how the events fire and help you understand serves as a starting point where you can put your code that does the more interesting stuff.

// Hook up Application event handlers.
var app = Sys.Application;
app.add_load(ApplicationLoad);
app.add_init(ApplicationInit);
app.add_disposing(ApplicationDisposing);
app.add_unload(ApplicationUnload);


// Application event handlers for component developers.
function ApplicationInit(sender) {
var prm = Sys.WebForms.PageRequestManager.getInstance();
if (!prm.get_isInAsyncPostBack())
{
   prm.add_initializeRequest(InitializeRequest);
   prm.add_beginRequest(BeginRequest);
   prm.add_pageLoading(PageLoading);
   prm.add_pageLoaded(PageLoaded);
   prm.add_endRequest(EndRequest);
}
$get('ClientEvents').innerHTML += "APP:: Application init. <br/>";
}
function ApplicationLoad(sender, args) {
$get('ClientEvents').innerHTML += "APP:: Application load. ";
$get('ClientEvents').innerHTML += "(isPartialLoad = " + args.get_isPartialLoad() + ")<br/>";
}
function ApplicationUnload(sender) {
alert('APP:: Application unload.');
}
function ApplicationDisposing(sender) {
$get('ClientEvents').innerHTML += "APP:: Application disposing. <br/>";

}
// Application event handlers for page developers.
function pageLoad() {
$get('ClientEvents').innerHTML += "PAGE:: Load.<br/>";
}

function pageUnload() {
alert('Page:: Page unload.');
}

// PageRequestManager event handlers.
function InitializeRequest(sender, args) {
$get('ClientEvents').innerHTML += "<hr/>";
$get('ClientEvents').innerHTML += "PRM:: Initializing async request.<br/>";
}
function BeginRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Begin processing async request.<br/>";
}
function PageLoading(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdating", args.get_panelsUpdating());
var deletedPanels = printArray("PanelsDeleting", args.get_panelsDeleting());

var message = "-->" + updatedPanels + "<br/>-->" + deletedPanels + "<br/>";

document.getElementById("ClientEvents").innerHTML += message;
}
function PageLoaded(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: Finished loading results of async request.<br/>";
var updatedPanels = printArray("PanelsUpdated", args.get_panelsUpdated());
var createdPanels = printArray("PaneslCreated", args.get_panelsCreated());

var message = "-->" + updatedPanels + "<br/>-->" + createdPanels + "<br/>";
  
document.getElementById("ClientEvents").innerHTML += message;
}
function EndRequest(sender, args) {
$get('ClientEvents').innerHTML += "PRM:: End of async request.<br/>";
}

// Helper functions.
function Clear()
{
$get('ClientEvents').innerHTML = "";
}
function printArray(name, arr)
{
 var panels = name + '=' + arr.length;
 if(arr.length > 0)
 {
     panels += "(";
     for(var i = 0; i < arr.length; i++)
     {
         panels += arr[i].id + ',';
     }
     panels = panels.substring(0, panels.length - 1);
     panels += ")";
 }
 return panels;
}

Friday, July 18, 2008

Don't be afraid of Generics in C#

I have been really slow to start using Generics and I have been even slow about writing my own methods that make use of Generics in C# (.NET 2.0 or newer). Today I realized exactly how easy it is to write a very generic method and have it use any type you want it to. This is of course the beauty of Generics. Without rambling anymore about my reluctance, here is how you do it. Let's assume that you are writing a bunch of methods that are all the same except they take different type of objects or even primitives as parameters. Here is a simple example of what you could write for each type you want: public static void AreEqual(int a, int b) { return a.Equals(b); } public static void AreEqual(string a, string b) { return a.Equals(b); } This is trivial example where the logic of the code is VERY simple. Imagine if that was a complex algorithm like searching or sorting. Would you really want to have that logic duplicated for each type that you want to work with. Of course not. Again, the prime reason for using Generics. Here is what you could write using Generics (Write once for ALL types): public static void AreEqual<T>(T a, T b) { return a.Equals(b); } You'll notice it looks very similar to the non-generic code except that it uses T instead of a type that you are used to. T is a special placeholder for what type the calling code wants it to be. Here is how you would call the non-generic code: bool retval = AreEqual(1, 0); bool retval = AreEqual("xxx", "yyy"); Here is how you could call the generic code: bool retval = AreEqual<int>(1,0); bool retval = AreEqual<string>("xxx", "yyy"); The syntax is a little strange at first in the end I find it very easy to use. It helped me to think of it as a runtime search and replace of 'T' with the type I currently want to use.

Can't publish Visual Studio 2005 Web Site because access denied error

If you get an error like "Access to the path 'C:\Documents and Settings\username\Local Settings\Temp\~6d4\bin\App_WebReferences.compiled' is denied." when you use the VS2005 | Build menu | Publish Web Site and your site impersonates a user this may help. Open up Windows Explorer and navigate to the Temp directory specified in the path. In this example, go to "C:\Documents and Settings\usb00528\Local Settings\Temp". Now right-click on the Temp directory and go to the security tab. Add the user that you are impersonating (usually specified in you web.config) and give the user Read and Write permissions. Now re-try the Publish Web Site menu item and it should publish successfully now. Yeah!

Wednesday, July 16, 2008

Check Version of OVSD web-api.jar

When you use the HP OpenView Service Desk (OVSD) web-api.jar to write programs that access the OVSD server you should use the same version that the server is using. The obvious question soon becomes, how do I know what version of the web-api.jar do I have. To determine the version of your web-api.jar do the following: 1. Locate the web-api.jar file you are compiling against in your program. 2. Open a command prompt and cd to the directory that contains your web-api.jar, so that it is your current directory. 3. Now type (or copy and paste) java -classpath web-api.jar com.hp.ifc.sys.AppVersionInfo This should return something like: Acronym: SD Version: 4.5.0588.1706 (SP17) Company: hp OpenView Copyright: Copyright (c) 2004 Hewlett-Packard Development Company, L.P. All Rights Reserved. Description: service desk is a family member of the hp OpenView suite. ProductID: B4321 ProductName: hp OpenView service desk If you don't know what version your server is running the easiest way to tell is to open your client software and look at the start up splash page. If you want a more detailed answer like the above info, you can do the following: 1. Execute C:\Program Files\Hewlett-Packard\OpenView\service desk 4.5\client\bin\sd_version.bat by double clicking it. This should return the same thing as you got for the web-api.jar info.