How To Make Sure Two Divs Are The Same Height

I recently needed to make sure that two DIV tags always stay the same height even though both have variable content, driven from a database. I thought I would share the solution I used although would welcome any alternative ways of doing the same thing.

HTML

The basic HTML I started with is shown below:

<html>
<head>
<title>Maintaining DIV Heights</title>
<style type="text/css">
#divLeft
{
float:left;
width:49%;
border:1px solid #000;
}
#divRight
{
float:right;
width:49%;
border:1px solid #000;
}
</style>
</head>
<body>
<div id="divLeft">
<p>
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
</p>
</div>
<div id="divRight">
<p>
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
</p>
</div>
</body>
</html>

So it’s a rather basic file and the idea is that no matter how much text you type into either column, the heights will always remain the same.

Solution

The solution I used involved a little JavaScript that essentially:

  1. Finds the height of the two columns and stores those values in two variables. I have had to check for IE as IE and Firefox/Safari interpret offsetHeight and clientHeight differently.
  2. Decides which is taller – the left or the right.
  3. Makes the shorter column the same height as the taller column.

So I added the function below into the <head></head> area…

<script type="text/javascript" language="javascript">
function setDivHeights() {
if (document.all) {
var iLeftHeight = document.getElementById("divLeft").offsetHeight;
var iRightHeight = document.getElementById("divRight").offsetHeight;
}
else {
var iLeftHeight = document.getElementById("divLeft").clientHeight;
var iRightHeight = document.getElementById("divRight").clientHeight;
}
if (iLeftHeight > iRightHeight) {
document.getElementById("divRight").style.height = iLeftHeight + "px";
}
else {
document.getElementById("divLeft").style.height = iRightHeight + "px";
}
}
</script>

…and then added this piece of JavaScript to call the function in the <body> tag…

onLoad="setDivHeights()"

…such that the end result looked like:

<html>
<head>
<title>Maintaining DIV Heights</title>
<style type="text/css">
#divLeft
{
float:left;
width:49%;
border:1px solid #000;
}
#divRight
{
float:right;
width:49%;
border:1px solid #000;
}
</style>
<script type="text/javascript" language="javascript">
function setDivHeights() {
if (document.all) {
var iLeftHeight = document.getElementById("divLeft").offsetHeight;
var iRightHeight = document.getElementById("divRight").offsetHeight;
}
else {
var iLeftHeight = document.getElementById("divLeft").clientHeight;
var iRightHeight = document.getElementById("divRight").clientHeight;
}
if (iLeftHeight > iRightHeight) {
document.getElementById("divRight").style.height = iLeftHeight + "px";
}
else {
document.getElementById("divLeft").style.height = iRightHeight + "px";
}
}
</script>
</head>
<body onLoad="setDivHeights()">
<div id="divLeft">
<p>
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
</p>
</div>
<div id="divRight">
<p>
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
This is some text - this is more text - this is even more text...
</p>
</div>
</body>
</html>

An example of the solution can be found here. If you have padding as part of the divs then you need to do some jiggerypokery to get the heights to balance again by subtracting the top and bottom padding from the Firefox/Safari side.

For example:

If the top and bottom padding were 10px you would need to subtract 20.

var iLeftHeight = document.getElementById(“divLeft”).clientHeight – 20;
var iRightHeight = document.getElementById(“divRight”).clientHeight – 20;

If anyone has any better solutions than this then I would be very open to it. Anyway, hope this helps. As always, any feedback (positive or negative) is always appreciated.

Allowing Remote Assistance to accept the machine name as a parameter

In a previous post I talked about how the Program Builder functionality of Service Desk Express allowed me to launch the Microsoft Remote Assistance tool. Whilst this was neat, what I really needed was to be able to prefill the machine name on the remote assistance page with a machine name as shown below:

Remote Assistance Screen

Remote Assistance Screen

The first thing we needed to do was to hack the Remote Assistance tool to accept a parameter. To do this you need to open

C:WINDOWSpchealthhelpctrVendorsCN=Microsoft Corporation,L=Redmond,S=Washington,C=USRemote AssistanceEscalationUnsolicitedUnSolicitedRCUI.htm

using, for example Notepad. Near the top of the file there is a function called OnLoad that looks like:

function onLoad()
{
;
;
try
{
setTimeout("idComputerName.focus()",250);
g_oSAFRemoteDesktopConnection = oSAFClassFactory.CreateObject_RemoteDesktopConnection();
}
catch(error)
{
FatalError( L_RCCTL_Text, error );
}
;
return;
}

All we need to do is add a couple of lines of Javascript at the top of this function that basically says, if the QueryString of the passed URL (the bit after the ? in a URL e.g. p=51 in the case of http://www.joatit.com/wordpress/?p=51 ) is not equal to the word “machinename”, prefill the machine name in the idComputerName textbox. So after editing, the function should look like:

function onLoad()
{
;
;
try
{
if (window.location.search.substring(1)!= "machinename")
{
idComputerName.value = window.location.search.substring(1);
}
setTimeout("idComputerName.focus()",250);
g_oSAFRemoteDesktopConnection = oSAFClassFactory.CreateObject_RemoteDesktopConnection();
}
catch(error)
{
FatalError( L_RCCTL_Text, error );
}
;
return;
}

Ok, so save that and now we are ready to launch it from Service Desk Express. So as per the previous post, log onto the Service Desk Express application server and run builder.exe that lives in C:Program FilesBMCService Desk ExpressTools. You should be greeted with a screen that looks like the example below:

Program Launcher

Program Launcher

In the Filename textbox enter: RemoteAssistance.asp

In the Command line textbox enter:

C:WINDOWSPCHEALTHHELPCTRBinariesHelpCtr.exe -url hcp://CN=Microsoft%20Corporation,L=Redmond,S=Washington,C=US/ Remote%20Assistance/Escalation/Unsolicited/ UnsolicitedRCui.htm?machinename"

and click Build Launch File.

Now using Form Customisation you can add a Customised Toolbar Button of type link to, for example, the Machine Name field in the Inventory Item module, by specifying a URL of:

http://<SDEServerName>/SDE/RemoteAssistance.asp?machinename=$64$

So, the obvious question is, where does the $64$ come from? The answer lies by running the following SQL statement:

SELECT * FROM SMSYSDBINFO WHERE View_Name = 'Inventory Items'

If you find the Machine Name field in the ALIAS column and look across to the INTERNAL_COL_ID for that field, you will find 64.

The final “icing on the cake” comes by using the DB Admin Tool to expose that Machine Name field to the Incident module by adding a new virtual field (let’s say called ‘Asset Machine Name’) through the existing Seq.Inv.Item foreign key. Run the following SQL statement…

SELECT INTERNAL_COL_ID FROM SMSYSDBINFO WHERE View_Name = 'Incident' AND ALIAS = 'Asset Machine Name'

and then using Form Customisation you can add a Customised Toolbar Button of type link on the Incident form to that newly exposed field. Now you can launch the Remote Assistance tool from the incident form, populating the machine name direct from the selected asset!

Hope it helps – as always all comments very welcome!

Showing images in Service Desk Express

A colleague of mine recently asked me to take a look at a request a customer had that involved wanting to be able to view an image of the client on the Incident screen when the Client ID was selected.

My immediate suggestion was to create a calculated field in the clients module that was a concatenation of a URL and the Client ID field and then make that calculated field available in the Incident module via the Clients foreign key and use the Display Link functionality to view the image. The advantage of this scenario is that a) it is completely supported by BMC and b) the image is only downloaded when the service desk agent wants to see the client’s mugshot.

Unfortunately, this was not what the client wanted. They wanted the image to actually show on the incident screen. This is how I managed it…

Using the customisation wizard I added a standard image to Incident form, saved the form and then viewed it in Service Desk Express (SDE). I then viewed the source code produced by SDE for this form and noticed that it gave my new image the ID of IMAGE2. I needed a directory where I could save the clients images so I created a subdirectory of the Images folder called Clients and saved each client’s image as a jpg using their Client ID such that mine would be ABARBER.jpg. What I now needed was a couple of simple Javascript functions that would swap my image with the client’s image:

function ImageSwap(sClientID)
{
var clientImage = document.getElementById('IMAGE2');
if (clientImage)
{
clientImage.onerror = ImageSwapError;
clientImage.src="images/Clients/" + sClientID + ".jpg";
}
}


function ImageSwapError()
{
this.src="images/NoImage.gif";
}

All the ImageSwap function does is check if IMAGE2 exists on the form (as you may have a form where it does not exist) and swaps the image appropriately. If the client’s image does not exist in the directory then it will throw an error and hence call the ImageSwapError function that just replaces the image with simple NoImage.gif. Notice that the NoImage.gif is to be located in the images folder NOT the images/Clients folder. This allows you to use that image on the form by default.

That was the easy bit. Now I needed to know where to put this function and also how to call it to make it do something. The answer came from the commonscript.js file located (by default) in D:Program FilesBMCApplication ServerScripts. I added my little functions just before another function that I was going to need – function FieldTabOut(). Now if you scroll all the way to the bottom of this function FieldTabOut(), after the …

//END - #Bug 30044

… line but before the closing }, I added my call to my ImageSwap function:

if(CommonModuleObj.ViewName == "24") ImageSwap(document.all("36").value)

Ok, so what does that do. Well basically it says, if the form is an incident form (that’s the ViewName == “24” bit) call my ImageSwap function passing the value of the Client ID textbox (that’s the document.all(“36”).value bit). Perfect, or so I thought. I saved the commonscript.js file and gave my server an IISRESET just in case and tested my “amazing” solution. It worked – sort of…

The problem was that it only worked when I tabbed out, not when I clicked on the popup button to find the client. Another hunt around commonscript.js provided my answer. In the top third of the file there is a function called function OpenPopup(). Once again I scrolled right to the bottom of this function, after the …

//38223 - End
}
strAddWhereClause = ""

…line and before the closing }, I added my call to my ImageSwap function again:

if(CommonModuleObj.ViewName == "24") ImageSwap(document.all("36").value)

I saved the file and gave my server another unnecessary IISRESET and it worked. I guess it goes without saying that this is a completely unsupported hack but it did achieve the desired effect.