Category Archives: JavaScript

My tutorials on JavaScript, mainly guides to using my JavaScript libraries. These are pretty much all outdated now, but the code’s still available if anyone wants to clean it up and use it.

Update on JS string concatenation

Somebody over at Slashdot has just pointed out a method of easily concatenating numbers. Although this is helpful, it can't address the underlying problem, which is that JavaScript shouldn't be using the + operator for two things, and it still doesn't address my main problem of JS concatenating instead of adding two numeric strings together. :(

JavaScript string concatenation

I've been coding JavaScript quite a lot for ABXY recently, and one thing which has got me really annoyed (apart from JavaScript's odd and overly-flexible "OOP" architecture) is its + operator.

In theory, the + operator is brilliant. Instead of being boring, and only doing one thing, it can be used for both numerical addition, and string concatenation. That's fine, you might say, but tell me; have you ever considered what happens when you want to add together two numerical strings, or concatenate two numbers?

The answer is that in the first instance, JavaScript will concatenate the strings, and in the second, it will add the two numbers together. That's perfect, according to the design, but it's not helpful. :( Most input and other variables in JavaScript are strings, so every time you want to add two numerical strings together, you have to cast them as numbers, using the parseInt or the parseFloat function, which is easy to forget at best, and downright inefficient at worst.

This is awkward, and unlike the rest of JavaScript; in other situations, JavaScript will happily cast between types to find two which match the operation you're trying to perform. Why is it different here? It's different because JavaScript doesn't know whether you're wanting to concatenate, or to add, and this is the underlying problem. JavaScript should follow PHP's example, and have separate addition and concatenation operators (+ and ., respectively).

JavaScript: AJAX

Continuing in my series of articles on my JavaScript library, I am doing my second article about my AJAX JavaScript file. The first article was written right at the start of the AJAX craze, and was (in hindsight), rather badly written. The JavaScript provided with it was too, quite badly written, and I've since revised my JavaScript (without telling anybody) several times. This morning, version 2.0.0 landed safely in my private SVN repository, and it is this that I am going to talk about.

Since the first version of my AJAX code, two major changes have been made (and many minor ones). The first change was to abolish the awful <resultpos> idea, splitting each function in two (i.e. when adding a comment, instead of having the same function called on the client side originally and when the data packet is received from the server, two separate functions would be called). The second major change was completed only recently, and has enabled multiple simultaneous requests to be made without fear of the packets getting mixed up.

Also present in this version is new functionality in the form of AJAX popovers. No longer are complete pages limited to being loaded through an HTTP request; using the popover functions in this script will enable you to have pages load as popovers on top of the current page.

This functionality isn't meant to be used for advertising (certainly not!), but the terminology was too good to lose. Imagine a scenario where you have a user who wants to log in, but making a complete HTTP request is just too much of a drag for them, and it's flashier to do it using that wonderful buzzword: AJAX. The user clicks the "Login" link, and instead of a new page loading, and them losing where they were in the current page, a popover appears with the username and password inputs. The user duly enters their details and clicks "Login", to have the login popover fade out, and their login to be authenticated.

Admitted, it doesn't have a massive range of uses, but it certainly is good for adding that "wow" factor to a website or application.

So…on to the script file itself. The script doesn't require any other files for pure AJAX usage, but if you want to use popovers, you'll need to include my general JavaScript library, and if you want fading, you'll need to include the GUI script file I previously wrote about.

To include the script in your page, you'll need to add the appropriate tag to the <head> tag of your document:

<script type="text/javascript" src="http://tecnocode.co.uk/sources/client/ajax.js" />

However, this file on its own won't really get you anywhere: you still need some CSS to prettify the popovers, and another script file to contain implementation-specific AJAX JavaScript. This file, you'll have to write yourself (typically producing ajax_custom.js), but I've provided some CSS already, which can be included by placing the following line in your <head> tag:

<link href="http://tecnocode.co.uk/sources/client/ajax.css" rel="stylesheet" media="all" type="text/css" />

Use of the script is quite simple. To initiate an AJAX transaction, simply call the load_XML_doc() function, passing the URL you want to load (with any data you want to pass as escape()d GET parameters) as the only parameter. The function will perform the transaction, calling the JavaScript callback function specified in the packet when the XML data packet is received.

Each XML packet must be in the following format:

<response>
	<method>[callback function name]</method>
	<result>[result markup]</result>
</response>

This latest version of my code also supports messages and errors returned by the server, using the first following XML packet for messages, and the second following XML packet for errors:

<response>
	<message>[message text]</message>
	</response>
<response>
	<error>[error code or name]</error>
	<message>[error message text]</message>
</response>

Errors and messages are handled transparently by the AJAX code, so implementation-specific code need not worry about it.

Speaking of implementation-specific JavaScript, it is a bit of a hazy subject, so an example would be in order. The example I'll use is the AJAX comment submission code form this very website, which requires several of my JavaScript libraries not previously explained. You'll just have to live with that.

Implementation-specific JavaScript is split into two functions: a function called to build the request URL and initiate the transaction, and a function to be called when the XML packet is received from the server.

This first function takes six parameters, specifying the details of the comment: author, email, comment, rating, post_id, parent_comment. The function is called in place of submitting the comment form, with the last two parameters hard-coded into the markup by the server:

function add_comment(author,email,comment,rating,post_id,parent_comment)
{
	//Take the specified input, and make the query
	if(!check_form(form)) return false;
	var url="./index.php?media=xml&page=blog&paragraph=add_comment&id="+escape(post_id)+"&parent_comment="+escape(parent_comment)+"&author="+escape(author)+"&email="+escape(email)+"&comment="+escape(comment)+"&rating="+escape(rating);
	load_XML_doc(url);
	return false;
}

Note that the function also calls check_form, to make sure all the fields are filled in correctly. This function is from my form validation JavaScript, which I hope to write about in the future.

So, this function has started the request, and now the client is waiting for news of the packet. Usually, this will be very fast (that's why I decided not to put an activity indicator on the page), but sometimes it won't; you might want to consider putting a little activity indication "throbber" into pages when using AJAX.

The server processes this request. In this case, it takes the comment data which has been submitted (notice that it was all escape()d), checks if it's all valid, and if so, writes it to the database. It then returns an appropriate XML packet, with a <method> of add_comment (not add_comment_response: the "_response" is added on the client-side). add_comment_response is then called:

function add_comment_response()
{
	//Response mode: parse the response, and see what the server says about our submitted comment
	//Our <result> will be the HTML for the comment (boolean)
	if(AJAX_RESULT)
	{
		//Display the comment, remove a class="no_x" element (if applicable) & clear the form fields (make sure we don't clear locked ones)
		var container=document.getElementById("comments_container");
		var comment_form=document.getElementById("comment_form");
		var i,random_id,cloned_child;
		var elements=getElementsByClassName(container,"no_x_comments");
		for(i in elements)
		{
			random_id=assign_random_id(elements[i]);
			fade_object(random_id,0.1,20,false);
			setTimeout("document.getElementById('comments_container').removeChild("+random_id+")",240);
		}
		for(i=0;i<AJAX_RESULT.childNodes.length;i++)
		{
			cloned_child=AJAX_RESULT.childNodes[i].cloneNode(true);
			if(cloned_child.style) cloned_child.style.opacity=0;
			container.appendChild(cloned_child);
			if(cloned_child.style)
			{
				random_id=assign_random_id(cloned_child);
				fade_object(random_id,0.1,20,true);
				wait(240);
			}
		}
		clear_form_inputs(comment_form);
	}
	else
	{
		window.alert("Your comment was rejected by the server. Please amend any errors and try again.");
	}
}

This function isn't passed any parameters. (Perhaps it should be? I'm looking into revising this functionality sometime in the future.) It accesses the global variable AJAX_RESULT to see what's there. In this example, the result contains all the markup for the submitted comment, so that it can just be popped (using the DOM) into place after all the other comments in the page.

Half of the complexity of this function is due to the use of fading from my GUI JavaScript, and the use of the DOM to insert the retrieved markup into the document instead of using outdated methodologies such as innerHTML.

Another feature of version 2 of my AJAX JavaScript is the popover functionality. It allows you to create popovers to perform tasks related to (or required by) the current page without refreshing.

The markup for the popups is retrieved when required from the server, reducing the amount which has to be initially downloaded. For example, you could have a "Login" link, which has an onclick handler as follows:

<a href="./?page=login" title="Follow this link to login." id="login_link" onclick="Javascript: return load_XML_doc('./?page=login&ajax');">Login</a>

Without JavaScript, it just takes you directly to the login page, but if you have a capable browser, it loads up a special version of the page (encased in one of the previously-described XML packets) through AJAX.

The return packet would have a <method> of "login", which would call the first of the two custom JavaScript functions required to do a popover (you can cut this down to one function if it's a non-interactive popover, such as a message):

function login_response()
{
	//Instantiate a popover
	if(AJAX_RESULT)
	{
		var login_link=document.getElementById("login_link");
		var x_pos=findPosX(login_link);
		var y_pos=findPosY(login_link);
		if(AJAX_RESPONSE.getElementsByTagName("redirect")[0])
		{
			setTimeout("window.location='"+AJAX_RESPONSE.getElementsByTagName("redirect")[0].textContent+"';",2000);
		}
		do_ajax_popover("Login",AJAX_RESULT,x_pos,y_pos);
	}
	else
	{
		window.alert("The server could not return the login form. Please try again.");
	}
}

This code is called once the markup has been retrieved from the server, and works out the position at which to spawn the popover, then spawns it. In this example, the position is worked out as the position of the login link the user followed, but other things may be done.

The popover has now been displayed; what to do now? Well…you'd want to have the login carried out through AJAX too, just to capitalise on the situation. This can be done. :)

The first child node of the popover is always given a special attribute: popover_id. This contains the unique ID of the popover containing the markup, so that multiple popovers can utilise the same JavaScript simultaneously without getting tangled. In this example, the login form calls a JavaScript function (do_login) instead of being submitted normally, although it can fall back to that if required:

function do_login()
{
	if(document.getElementById("login_form").getAttribute("popover_id"))
	{
		var url=document.getElementById("login_form").getAttribute("action")+"&ajax&username="+escape(document.getElementById("username").value)+"&password="+escape(document.getElementById("password").value);
		load_XML_doc(url);
		close_ajax_popover(document.getElementById("login_form").getAttribute("popover_id"));
		return false;
	}
	else return true;
}

This is basically just another URL-generation function, with the addition of a call to close_ajax_popover with the popover ID to close the popover after the login data has been submitted. Once the return packet arrives for this request, it will call login_response again (as it will have a <method> of "login"), but it will also have a <redirect> tag present, which will redirect to the logged-in page after it has displayed the message which was returned by the AJAX request. It's a bit of a mouthful to get your head around. ;)

I have put together a small sample page showing popovers in a little more detail (i.e. interactively).

Now for a more technical view of the functions:

Function declaration Description
public bool load_XML_doc(string url) Request the specified URL through an XMLHttpRequest object. Return false on success, and true on failure (for events).
private void process_request_change() Processes a data packet received from the server after a request.
public bool do_ajax_popover(string title_text,dom_tree snippet,int x_pos,int y_pos) Create a popover and make it appear in the page.
private void _close_ajax_popover(dom_event event) Destroy a popover after the "Close" button has been pressed.
public void close_ajax_popover(string popover_id) Destroy a popover by ID.

The CSS is quite simple, and all the classes and IDs generated by the Javascript already have a rule in the CSS file. I have provided a brief explanation of each class, and an image to depict what it is:

Class / ID Description Applicable element(s) Descriptive image
.popover_container The main popover "window" element. <div> .popover_container
.popover_content The content in the popover, retrieved from the server. <div> .popover_content
.popover_bottom A currently unused element at the bottom: could possibly be used for a "tail". <div> .popover_bottom
.popover_title The popover's title. <h2> .popover_title
.popover_close The "Close" button. <a> .popover_close

If you do use this script, please download it and host it with your website; do not leech my bandwidth! Additionally, please follow the terms of the license to the letter. I hope this is of use to somebody. :)

JavaScript: GUI

Following on from my article on JavaScript popup messages, I am going to try and get through my entire JavaScript library, releasing it to the public. This is a good thing all round, as I get to improve my JavaScript to bring it up to release quality, and then it gets released. :)

This script file is the GUI library. Although there are many functions for dealing with the interface in other script libraries, the functions in this file are the most so, and aren't relevant to anything else.

It doesn't require any other library files, although having it as the only library file won't get you anywhere quickly, so it would be best to include my general library first, by putting the following markup in your <head> tag:

<script type="text/javascript" src="http://tecnocode.co.uk/sources/client/general.js" />

The next step is obviously to include the GUI JavaScript itself, which is best left untouched, but that's by no means absolute:

<script type="text/javascript" src="http://tecnocode.co.uk/sources/client/gui.js" />

Currently (January 2006), there are only three functions in the file: a function to fade things in and out, and two functions for retrieving the position of an element. These two functions aren't actually mine; credit for them must go to quirksmode.org, although I'll probably customise them in the future.

To fade an element in, you must first set its opacity to 0:

element.style.opacity=0;

Then, you can use the fade_element function to gradually fade the element in:

fade_object(element.getAttribute("id"),0.1,10,true);

This function call increases the opacity of the specified element ID by 0.1 (10%) every 10 milliseconds. Note that after calling this function, execution continues in the current function (i.e. the fading starts in a new thread), so if you have code after the call to fade_object which depends on the fade, you'll have to delay it somehow.

It is just as easy to fade something out: you just need to set the fourth parameter in the call to fade_object to false; this decrements the element's opacity by the specified amount at the specified frequency, instead of incrementing it. Bear in mind that you'd have to set the element's opacity to 1 before fading it out, instead of setting it to 0.

Whilst calling the JavaScript in this manner is backwards-compatible, the title of the message is just "Message", and you cannot pass DOM snippets in — only plain text can be passed as the function parameter.

The two other functions are designed to retrieve the position (left and top, respectively) of a specified element on the page.

If I wanted to find the X-position (distance from the left-hand edge of the rendering area) of an element, I'd make the following function call:

var left_distance=findPosX(element);

I could do a similar thing to find the distance from the top of the rendering area:

var top_distance=findPosY(element);

Now for a more technical view of the functions:

Function declaration Description
public void fade_object(string fade_element_id,float add_opacity,int frequency,bool increasing_opacity) Fade the specified element in or out. This function doesn't return anything, and spawns a new thread for its execution.
public int findPosX(dom_element obj) Finds the distance from the left-hand edge of the rendering area of the specified element.
public int findPosX(dom_element obj) Finds the distance from the top edge of the rendering area of the specified element.

If you do use this script, please download it and host it with your website; do not leech my bandwidth! Additionally, please follow the terms of the license to the letter.

JavaScript: popup messages

With the recent batch of changes to the site, I've introduced a number of my new JavaScript files to the domain. I feel that they're too good to be kept to myself, and as such, they're released under the GPL. The first one I'm going to talk about is the popup message JavaScript, which replaces the standard browser message popup with a custom XHTML one.

A JavaScript popup message in use on drboblog.Now I'm not usually one to replace browser features, as I believe that the browser and the web page should be kept separate, much as the structure and the presentation should be kept separate. However, when it comes to browser message popups, there really is no alternative but to replace them. They're ugly, unskinnable, and can really ruin what would otherwise be a good page.

So to replace the browser popup windows, I've written a Javascript file. It has functions for creating, controlling, and controlledly-detonating custom XHTML message popups, and replaces the standard browser window.alert("message"); function when included in the page. When activated, it disables all the links and forms in the page below it, and re-enables them when dismissed.

The code is pretty simple, and most of it is just bulk to generate and manipulate elements in the DOM, so it doesn't need explaining. However, I feel the usage of the code does require some explanation, and presents a nice opportunity for another example page.

To begin with, you must include my standard JavaScript library file, which is also available under the GNU GPL. This is accomplished using the following XHTML in the <head> tag of your page:

<script type="text/javascript" src="http://tecnocode.co.uk/sources/client/general.js" />

The next step is obviously to include the popup message JavaScript itself, which I would appreciate if you left in its original form, but since that's not a requirement of the license, you don't have to: :P

<script type="text/javascript" src="http://tecnocode.co.uk/sources/client/popup_message.js" />

This, too goes into the page's <head> element, but after the inclusion of the general library. On my website, I have moved site-specific popup message functions into a separate popup_message_custom.js file and included it, but this is by no means a requirement.

The final inclusion is of the CSS file. This file should obviously be customised to your own tastes and site design, but the default design is pretty neutral. This is included with the following markup (once again in the <head> section):

<link href="http://tecnocode.co.uk/sources/client/popup_message.css" rel="stylesheet" media="all" type="text/css" />

Now we get onto the actual calling of the functions necessary to create a popup message. You can call the following function anywhere you like to create a popup message, but a sensible place to put it would be in the onclick event of a link, or something else:

popup_message("window_title",message);

Here, you would obviously replace window title with the popup message's required title, and message with the message you want, which should be a JavaScript DOM snippet. Alternatively, you can pass a string, but this is messy. You should note that this function always returns false, to facilitate the cancelling of events.

However, in some circumstances, you might not know if the file has been included or not, and in any case, for backwards-compatibility, it is preferable to use the window.alert("message"); function instead of the script-specific function described above:

window.alert("message");

Whilst calling the JavaScript in this manner is backwards-compatible, the title of the message is just "Message", and you cannot pass DOM snippets in — only plain text can be passed as the function parameter.

Now that the details of using it have been cleared up, let's finish off with a slightly more technical description of the JavaScript functions, and the CSS:

Table 1: popup_message.js functions
Function declaration Description
public bool window.alert(string message) The original, unmodified browser popup message creation function, or a reference to popup_message("title",message); if popup_message.js has been included. Always returns false.
public bool popup_message(string window_title, dom_tree|string message) The custom popup message creation function, which creates a whole new element tree, and displays it on the page. Always returns false.
private void hide_popup_message(dom_event event) The function to destroy (remove) a visible popup message. It should not be called by any custom code unless you really know what you're doing.

The CSS is quite simple, and all the classes and IDs generated by the JavaScript already have a rule in the CSS file (although you could have styles for individual popup message IDs, but this is going too far). I have provided a brief explanation of each class, and an image to depict what it is:

Table 2: popup_message.js classes and IDs
Class / ID Description Applicable element(s) Descriptive image
.popup_message The main popup message "window" element. <div> .popup_message
.popup_message_title The title of the popped-up message. <h2> .popup_message_title
.popup_message_message The container for the message. <div> .popup_message_message
.popup_message_button The "OK" button used to dismiss the popup message. <button> .popup_message_button

A final note must be about the files I've provided. If you do use this script (and the CSS), please download it and host it with your website; do not leech my bandwidth! Additionally, please follow the terms of the license — I'm giving you something, and I only ask for a little in return.

AJAX

OK. I've been wanting to write an article about the myriad wonders of Ajax almost since I first found out about it. Ajax is a very powerful and flexible technology (almost as good as XML :P), and I love raving about it. I've just found some time to write this article; I'm currently rather depressed with some work I've been doing for the past 8 hours, so I thought now was as best a time as any to sit down and spout. :)

Ajax is one of the most flexible technologies to come to fruition since the birth of the web. It's actually been around for quite a while, but lack of widespread browser support, and developer ignorance have kept it at bay. It's basically just a simple application of Javascript to download new data and utilise it, without actually reloading the whole page. This allows developers to keep server load down; load data unbelievably quickly make some snazzy interfaces; and generally impress the users: Ajax is a flashy technology.

So, on to the actual code.

The implementation of Ajax is rather simple - all the data is transferred using XML packets:

  • The transaction is initiated from the client-side, using Javascript
  • The Javascript uses an XMLHttpRequest object (or equivalent) to fetch a page from the server (typically from a dynamic script)
  • It sets an "onreadystatechange" function to catch the response, and then exits
  • The "onreadystatechange" function catches the response from the server, and parses the XML
  • It then dynamically calls the respective function to deal with the actual data received

var req;

function load_XML_doc(url)
{
if(window.XMLHttpRequest)
{
//Branch for decent browsers' XMLHttpRequest object
req=new XMLHttpRequest();
req.onreadystatechange=process_req_change;
req.open("GET",url,true);
req.send(null);
}
else if(window.ActiveXObject)
{
//Branch for IE :(
req=new ActiveXObject("Microsoft.XMLHTTP");
if(req)
{
req.onreadystatechange=process_req_change;
req.open("GET",url,true);
req.send();
}
}
}

This function is called on the client-side when you want to initiate an Ajax transaction. It requests a document from the server, sets a function to catch the response, then disappears. It uses different methods of communication for different browsers (Gecko / MSIE), but the end result is still the same.

function process_req_change()
{
//If req is 'complete'
if(req.readyState==4)
{
//If status is 'OK'
if(req.status==200)
{
//Process the result
response=req.responseXML.documentElement;

var method=response.getElementsByTagName("method")[0].firstChild.data;
var result=response.getElementsByTagName("result")[0].firstChild.data;
var resultpos=response.getElementsByTagName("resultpos")[0].firstChild.data;
resultpos--;

var eval_text=method+"(";
for(var i=0;i<resultpos;i++)
{
eval_text=eval_text+"'',";
}
eval_text=eval_text+"result);";

eval(eval_text);
}
else
{
alert("There was a problem retrieving the XML data:n"+req.statusText);
}
}
}

This function receives the XML data packet sent by the server, extracts the useful data, and calls the right function to handle said data. Note that the XML handling is all done through the DOM. No IE-only old methods for Ajax. ;)

This is all fine and well...but without the XML data format, everyone's a bit stuck:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response>
<method>get_databases</method>
<result></result>
<resultpos>5</resultpos>
</response>

There are three main points of interest here:

  • The "method" tag: it contains the name of the Javascript function that will handle the returned data
  • The "result" tag: it contains the actual data to be used
  • The "resultpos" tag is my own addition: if you want to have the contents of the "result" tag passed to the "method" Javascript function in some parameter position other than 1, set it here. ;)

This data has to be sent with a certain MIME type ("text/xml"). The following PHP code will achieve that:

header('Content-Type: text/xml;charset=iso-8859-1');
header('Vary: Accept');

So, we have two abstract functions for dealing with XML-RPC, a format for the XML data packets, and a snippet of PHP for header manipulation. Time to write a sample Javascript function to actually call something!

function get_message(message_number,response)
{
if(response!='')
{
//Deal with the response
window.alert("Received message: "+response);
}
else
{
//Make the query!
var url="sample.php?message_number="+message_number;
load_XML_doc(url);
}
}

This function is exceedingly simple, but it manages to deal with the sending and handling of the data.

Coupled with a PHP script ("sample.php"):

<?php
header('Content-Type: text/xml;charset=iso-8859-1');
header('Vary: Accept');

echo '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<response>
<method>get_message</method>
<result>';

switch($_GET['message_number'])
{
case 1:
echo 'Hello world!';
case 2:
echo 'Goodbye world.';
default:
echo 'Unknown message_number.';
}

echo '</result>
<resultpos>2</resultpos>
</response>';
?>

That should work, and give you a nice little spiced up "Hello world" script - using Ajax

To make things a little friendlier for the user, you could use DOM manipulation to place results in the page dynamically.

For some neat (even if I do say so myself!) examples of Ajax in action, see Helios :D