JavaScript Tabs

Tabs are awesome. When tabbed browsing first came out, I was loathe to pick it up, and it was only the released of the Google Chrome™ browser which converted me. Now I cannot do without it. One of the first things I wanted to make when I was learning JavaScript was a website tab system. This is what I came up with.


//the JavaScript function
xiTabCurrent=1;
function xiTab (n)
{
if (document.getElementById("tab"+n).style.display == "none")
{
	document.getElementById("tab"+xiTabCurrent).style.display="none";
	document.getElementById("button"+xiTabCurrent).className=document.getElementById("button"+xiTabCurrent).className.replace(" tabselected","");
	document.getElementById("tab"+n).style.display="inline-block";
	document.getElementById("button"+n).className+=" tabselected";
	document.getElementById("button"+n).blur();
	xiTabCurrent=n;
}
}

//The tab buttons
<div class="tabheader">
	<input type="button" id="button1" class="tab tabselected" value="General" onclick="xiTab(1)" />
	<input type="button" id="button2" class="tab" value="Extra" onclick="xiTab(2)" />
</div>

//The tab containers
<div id="tab1" class="tabcont" style="display:inline-block">
</div>
<div id="tab2" class="tabcont" style="display:none">
</div>

//The styling
.tab { border: 1px solid #9c9c9c; border-bottom: none; background-color: #eaeaea; margin: 0px 0px 0px 2px; display: inline-block; cursor: pointer; padding: 2px 5px 4px 5px; z-index: 1; position: relative; }
.tab:first-child { margin-left: 0px; }
.tab:hover { background-color: #c7c7c7; }
.tabheader { font-size: 14px; }
.tabcont { border: 1px solid #9c9c9c; background-color: #eaeaea; margin: 0px auto 0px auto; padding: 5px; width: 880px; position: relative; top: -1px; z-index: 100; }
.tabselected { background-color: #eaeaea; z-index: 900; position: relative; padding-top: 5px; }
.tabselected:hover { background-color: #eaeaea; }

From every test I have run, this solution works completely on every browser, with one small exception. When run with Opera, the tab will not blur (lose focus) after you press the button, which can be aesthetically unpleasant. However all the other browsers, including IE, work fine. The function sits at the top of the page (or in an external .js file) in a script tag. It is important that the xiTabCurrent variable is outside the function, as it sets the currently selected tab when the page loads. The tab containers should sit directly after the buttons to allow the styles to work correctly. You can see an example here.

How it works:

<input type=”button” id=”button1″ class=”tab tabselected” value=”General” onclick=”xiTab(1)” />
When the button is pressed, it sends the function a number, related to which button has been pressed. This number links to the id of the button and of the tab container, button1 and tab1 respectively. It is important that these numbers increment on each additional tab, and do not repeat. The function will then change the styling of the button (to show it is selected) and the tab (to change it from hidden to visible). It will then change the previously selected tab to not-selected (button) and hidden (tab container). Simple.

Windows 7 Gadgets Pt III

A Gadget can be made better in lots of little ways. There is a command which can run a program, and another to use a verb on a specific file (ie “open”). All of these are safe and secure as the gadget cannot actually create or modify files, so no viruses can sneak through.


//Open a network location
<a href="\\fileserver\share">Open Share</a>

//Open a remote desktop connection
function openRDP (v)
{
	System.Shell.execute("C:\\Windows\\System32\\mstsc.exe",v);
}
<a onclick="openRDP('/v:fileserver')">Remote to fileserver</a>

//Open a text file
var filepath = System.Shell.itemFromPath("C:\readme.txt");
filepath.invokeVerb("open");

If you are working on Gadgets whilst they are live on your desktop, the following function is pretty much necessary: window.location.reload(). Add a button with this as the “onclick” function, and you can refresh the page live, updating it with most changes you may have made.


<input type="button" id="refresh" value="Refresh" onclick="window.location.reload()" />

Sorting multi-dimensional Arrays

A quick post, on sorting multi-dimensional arrays with JavaScript.

The problem:
I have a multi-dimensional array, and I wish to sort the first dimension by a single record in the second dimension. For the sake of argument, let us say record “0″.

The data:
See this Page.

The solution:


function sortMulti(a,b)
{
	return a[0] - b[0];
}
myarray.sort(sortMulti);

Simple really, when you think about it. See the array data page for the output. The data in the second dimension is unchanged, but the whole of the second dimension has been sorted in the first dimension by the first record in the second.

The AJAX, the JavaScript and the XML.

I headed into the wardrobe of XML and AJAX recently, in the never ending pursuit of dynamic Windows 7 gadgets. I set up an Apache server, threw in MySQL and PHP for good measure, and started playing around with fetching a table from a database for use in a Gadget, with a healthy mix of SQL, PHP, JavaScript, AJAX, and XML. I converted the data I pulled from the database into XML via PHP, so although I pointed the HTTP Request at a .php page, it was returning XML for me.

So far so good, this worked pretty much out of the box. My next step, and where the problems began to occur, was dealing in AJAX/JavaScript with an indeterminate amount of columns. The coding suggested on sites such as W3Schools looked untidy, and meant creating extra lines every time you added another column. I wanted to make it dynamic and free flowing, bouncing like a fawn across the moss covered slopes of a hill. I wanted to just add a pointer on the final output where the new column would sit for each additional column I created.

To accomplish this, I came up with the following code, after much blood and tears.


function getxml ()
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST",(_xml page_),"true");
xmlhttp.send();

xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
	var ajax_response_xml = xmlhttp.responseXML;
	var ajax_insert = "";
	var ajax_response_entry = ajax_response_xml.getElementsByTagName("entry");
	var ajax_response_elements = ajax_response_entry[0].childNodes.length;
	var ajax_response_elements_array = new Array();
	for (var i=0;i<ajax_response_elements;i++)
	{
		ajax_response_elements_array.push(ajax_response_entry[0].childNodes[i].nodeName);
	}
	var ajax_response_data_array = new Array();
	for (var i=0;i<ajax_response_entry.length;i++)
	{
		ajax_response_data_array[i] = new Array();
		for (var j=0;j<ajax_response_elements;j++)
		{
			ajax_response_data_array[i][ajax_response_elements_array[j]] = ajax_response_entry[i].getElementsByTagName(ajax_response_elements_array[j])[0].firstChild.nodeValue;
		}
		ajax_insert += ajax_response_data_array[i]["no"] + ": " + ajax_response_data_array[i]["message"] + "<br />";
	}
	return = ajax_insert;
}
}
}

This will convert an XML document/object into a multidimensional array, or in this case it was originally from a database, so the first dimension of the array is the record, the second dimension is “column name” => “value”. This probably isn’t the most efficient way of doing it, maybe it doesn’t even hold to pre-approved standards of coding, but I hope it is useful for someone.

The database I tested this with only had 2 columns, and here is the PHP I used to convert the database records into XML:


$xi_con = mysql_connect($xi_loc,$xi_user,$xi_pass);
if (!$xi_con)
{
	die('Could not connect: ' . mysql_error());
}
mysql_select_db($xi_db, $xi_con);
$xi_query = "SELECT * FROM tickets";
$xi_result = mysql_query($xi_query);
$xml_output = "<?xml version=\"1.0\"?>\n";
$xml_output .= "<entries>\n";
while ($xi_row = mysql_fetch_array($xi_result))
{
	$xml_output .= "\t<entry>\n";
	$xml_output .= "\t\t<no>" . $xi_row['id'] . "</no>\n";
	$xml_output .= "\t\t<message>" . $xi_row['message'] . "</message>\n";
	$xml_output .= "\t</entry>\n";
}
$xml_output .= "</entries>";
echo $xml_output;

I was more interested in the AJAX/JavaScript than the PHP, so this is obviously just a way to get the XML out there – I should really have used an iteration for the columns rather than explicitly creating a line for each. Never mind.

Windows 7 Gadgets Pt II

My next investigation was how to set up a persistent variable across sessions. Microsoft were of course one step ahead of me, and had created the Settings objects, which allow you to store an array of values, in the format key=value. This was all saved in a .ini file in

C:\Users\%username%\AppData\Local\Microsoft\Windows Sidebar

and was accessed by two commands; one to write the variables, and one to read them back. You can read through Microsoft’s manifesto on these here. These commands are intended to provide persistant settings, but it also provides you with a *very* basic database system, without the need to link to any external system. Here is a sample of how to use these.


function addvar(key,value)
{
    System.Gadget.Settings.write(key,value);
}

function readvar(key)
{
    return System.Gadget.Settings.read(key);
}

Microsoft also provide you with a better/faster way of storing strings, by using: System.Gadget.Settings.writeString() and System.Gadget.Settings.readString(). However they don’t appear to provide an easy way to clear a key, even setting it to “” will not remove it from the ini file. I can only conclude that they don’t expect you to want to remove settings…

Windows 7 Gadgets

I decided to make a Windows 7 desktop Gadget. I soon learnt that all they include are a simple XML file and some HTML, both of which I am to some degree familiar. So I put the kettle on to boil, and dived into the murky world of web design. Two hours later I resurfaced, with a more definate idea of what I was doing, and in the sure knowledge that the water in the kettle was now cold. I put it back on to boil, and set about making a Gadget from scratch.

The XML file is very simple, and you can read up on the basics here. The HTML base file, can also just be simply HTML. If you’ve ever made a web page before, then you can make a gadget. The one thing to remember is to set your body tag to the width and height you want the gadget to appear. If you want to do something more advanced with your gadget, you have the option of either JavaScript or JScript. Server side languages like PHP and ASP are not supported in a gadget unfortunately, but you can still do some cool tricks. Specific Windows Objects allow you to pull certain information directly from the host OS, such as network details, and the machine name. This was the feature that I was most interested in at the time, but I must say it took me a while to get it to work. Maybe (read: Probably) I am just dim witted. Here is the basic code to use it.


function getMachineName ()

{
    Device_Name.innerHTML = System.Environment.machineName;
}

Run this function from your “onload” event, and have something similar to the following on your page.


<div id="Device_Name"></div>

This will then dump the machine name inside this <div> whenever the page loads. After getting this to work, I was very pleased with myself, until I realised that the water in the kettle had gone cold again. Still, could have been worse. If you are thinking of writing a Gadget, then I would definitely recommend going on a crash course in JavaScript first, as a Gadget without JavaScript/JScript would be a boring Gadget indeed. More to follow on Gadgets!

Welcome to my new blog.

Lots of people seem to use a blog, but the most useful I have found are the IT gurus who post about experiences they have had, or tips and hints on using programs. This can be very handy if you are trying to do something “unusual”, which I seem to do a lot. So I thought I would start my own blog to keep track of my own forays into the unusual, and hopefully I will help *someone* along the way. Watch for new content!