function fancy_box() {
// Before calling, set the global array variables as in the following example
//      var f_box_class_name = ["classname_1", "classname_2"]; 'inner div' classes to be decorated. At least one MUST be specified
//      var f_box_css_prefix = ["rounded", "shadow"];  css styles to be applied. At least one MUST be specified
//		var f_box_color = ["red","#F7D58D"] // note 'color' and not 'colour'. Defaults to 'trans' (transparent)
//      var f_box_margin = ["auto", "auto", "leave"] If you want to override FFox's inability to handle margin:auto, specify "auto"to enable centering, otherwise specify "leave" or let it default  
//      var f_box_content_tag = ["img"]; // content tag types to be padded. Defaults to "img". If you want no tag, use "notag"; otherwise it will use the default tag
//      var f_box_content_pad = ["10px 5px 10px 5px", "5px"]; // padding. Defaults to "0px"
//      var f_box_attrib_srce = ["classdiv","content"]; // whose attributes we use to apply to the decoration divs. Defaults to "classdiv", i.e. the <div>  itself
// 		var f_box_sides_also = ["yes"]; // whether you want corners only or sides also. 'Sides only' is not supported! Defaults to "yes"
//
//
// The 'content' tags are the tags immediately within (i.e. children of) the inner divs 
// f_box_attrib_srce indicates the source of attributes (e.g. width) used to apply to the decoration divs.
// The source can either be the class_name div or a child of that div (e.g. an <img> tag). If the class_name div has more than one child with a qualifying f_box_content_tag, those of the first one found are used. 
// The entries in css_prefix, content_pad etc will normally correspond 1:1 with class_name, they may have fewer entries than
// class_name, in which case the last entry in each is used for the remaining class_names.
// Call from <body onload="fancy_box()"> or <frameset onload="fancy_box()"> or window.onload = fancy_box; 
// Note that window.onload will not allow parameters to be passed (no '()'), hence the use of global variables instead

var
divs_all = new Array(),
divs_subset = new Array(),
wk_content_pad, default_pad = "10px",
wk_sides_also, wk_sides_temp, default_sides_also = true,
temp = new Array(),
child = new Array(), 
attrib_srce, default_attrib_source = "classdiv",
attrib_srce_object, attrib_wk,
color, default_color = "trans",
wk_css_prefix,
wk_tag, default_tag = "IMG",
wk_margin, wk_margin_default = "leave",
idiv_height,
idiv_width,
idiv_pad_left,
idiv_pad_right,
idiv_pad_top,
idiv_pad_bottom,
idiv_margin_left,
idiv_margin_right,
idiv_margin_top,
idiv_margin_bottom,
idiv_float,
browser_css_level, // note: "IE", "Moz" or "Other"
browser_version, // note: IE version or -1 (i.e. not IE)
i1, i2, i4, i5, i6,
tag_mtch, tag_none,
regexp_pat = new RegExp(/px/g),
// the dummy entries below are to simplify the code; the first (outer)div
// will be the background-colour one without any CSS sheet entry
css_suffix = 
[
"dummy",
"_line_top",
"_line_right",
"_line_left",
"_line_bottom",
"_corner_tr",
"_corner_br",
"_corner_bl",
"_corner_tl"
],
css_repeat =
[
"dummy",
"repeat-x",
"repeat-y",
"repeat-y",
"repeat-x",
"no-repeat",
"no-repeat",
"no-repeat",
"no-repeat"
],
css_pos =
[
"dummy",
"top left",
"top right",
"top left",
"bottom left",
"top right",
"bottom right",
"bottom left",
"top left"
];
 
function getIEVersion()
{
  var rv = -1; // Return value assumes not IE 
  if (navigator.appName == 'Microsoft Internet Explorer')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
  }
  return rv;
} // ends function getIEVersion


function attrib_set() {
// when called, i2 is the index number of the div to be added
// But the note that i2 = 0 is the background div which has no CSS entry

// define to save repeating a chunk of code
if(i2 == 0)
	full_class_name = wk_css_prefix + "_background";
else
	full_class_name = wk_css_prefix + css_suffix[i2];

// IE 7 and below prefer 'className'. IE8 and above and FFox 3 and above like 'class'
if (browser_version >= 8 | browser_version == -1) 
	ndiv.setAttribute("class",full_class_name); 
else
	ndiv.setAttribute("className",full_class_name);

//doesn't work with IE<=7 if you use class instead of className
// In IE<=7, DOM property CLASS and HTML attribute className are supposed to work identically, but... 


// Set shape etc to be the same as the inner-to-be div
if(browser_css_level != "Other") {
// apart from the new outer div, force all margins and padding of divs to be zero so they overlay one another
// this allows the outer div if necessary to have margin left and right = auto for centering
if (i2 == 0) {
	
	ndiv.style.marginLeft = idiv_margin_left;
	ndiv.style.marginRight = idiv_margin_right;
	ndiv.style.marginTop = idiv_margin_top;
	ndiv.style.marginBottom = idiv_margin_bottom;
	// for future use......
	//ndiv.style.paddingLeft = idiv_pad_left;
	//ndiv.style.paddingRight = idiv_pad_right;
	//ndiv.style.paddingTop = idiv_pad_top;
	//ndiv.style.paddingBottom = idiv_pad_bottom;
    ndiv.style.cssFloat = idiv_float;

}
else
{
	ndiv.style.marginLeft = 0;
	ndiv.style.marginRight = 0;
	ndiv.style.marginTop = 0;
	ndiv.style.marginBottom = 0;
	ndiv.style.paddingLeft = 0;
	ndiv.style.paddingRight = 0;
	ndiv.style.paddingTop = 0;
	ndiv.style.paddingBottom = 0;
}

if (attrib_srce == "content") { // expand to border of inner tag
// Jscript gets confused here if we don't explicitly convert to numbers...


		if (idiv_width != "auto" && idiv_width.indexOf("%") == -1) {  // not auto or a %
			attrib_wk = 
				Number(idiv_width.replace(regexp_pat,""))
			+ 
				Number(idiv_pad_left.replace(regexp_pat,""))
			+	
				Number(idiv_pad_right.replace(regexp_pat,""));
			if (idiv_margin_left != "auto") {
				attrib_wk = attrib_wk + Number(idiv_margin_left.replace(regexp_pat,""))}
			if (idiv_margin_right != "auto") {
				attrib_wk = attrib_wk + Number(idiv_margin_right.replace(regexp_pat,""))}
			
			ndiv.style.width = attrib_wk + "px";
			}
		
		else
			ndiv.style.width = idiv_width;

	if (idiv_height != "auto"  && idiv_height.indexOf("%") == -1) {  // not auto or a %
		attrib_wk = 
			Number(idiv_height.replace(regexp_pat,""))
		+ 
			Number(idiv_pad_top.replace(regexp_pat,""))
		+	
			Number(idiv_pad_bottom.replace(regexp_pat,""));
		if (idiv_margin_top != "auto") {
			attrib_wk = attrib_wk + Number(idiv_margin_top.replace(regexp_pat,""))}
		if (idiv_margin_bottom != "auto") {
			attrib_wk = attrib_wk + Number(idiv_margin_bottom.replace(regexp_pat,""))}
		ndiv.style.height = attrib_wk + "px";
		}
	
	else
		ndiv.style.height = idiv_height;

} // end of 'content' bracket

else // keep height and width the same as the class div
{
	ndiv.style.width = idiv_width;
	ndiv.style.height = idiv_height;
}


// Adjust for IE8's error: it allows the bottom corner divs to position 1px too high up
// and this exposes part of the bottom line full width, appears to misplace the bottom line
// slightly downwards, and exposes a small 'tree trunk' of the bottom of the two side lines.
// Merely adjusting the bottom corner divs is not sufficient - exactly why is unclear!

// correct for error in IE 8 
if (browser_version >= 8) ndiv.style.marginBottom = "-1px";

// For i2 > 0, set background attributes to position the background URL
// else set the background colour
if (i2 == 0)
	{if (color != "trans") 
		ndiv.style.backgroundColor = color;
	else
		ndiv.style.backgroundColor = "transparent"; // should default .. but just in case...
	
	}
else
	{
	ndiv.style.backgroundRepeat = css_repeat[i2];
	ndiv.style.backgroundPosition = css_pos[i2];
	}
}
} // end function attrib_set

//
//        ..................MAIN INLINE CODE STARTS HERE..................
//


browser_version = getIEVersion(); // calls function below. -1 returned = not IE

if(typeof(f_box_class_name) == "undefined")  // note ==  equates when undefined or null
	alert("Error in fancy_box.js - No class names specified");

// Loop round each class_name
for (var i3 = 0; i3<f_box_class_name.length;i3++){
divs_subset.length = 0;
divs_all.length = 0;

// First list the divs. Select only the subset with the right class-name 
i2=0;
temp= document.getElementsByTagName("div"); // note that we add divs each i3 loop
for (i1=0; i1<temp.length;i1++) {divs_all[i1] = temp [i1];} // need to copy to remove assignment by reference. Slice() does not work!
for (i1=0; i1<divs_all.length;i1++) {
	if(divs_all[i1].className == f_box_class_name[i3]) {
		divs_subset[i2]= divs_all[i1];
		i2++;
	}
}

// Allow several classes to share the same content padding if necessary 
// We must do this NOW - i.e. BEFORE extracting the current styles of the inner div
// since the inner div may be resized by its content!
wk_content_pad = default_pad;	
if(typeof(f_box_content_pad) !== "undefined") {
if(f_box_content_pad.length <= i3) 
	wk_content_pad = f_box_content_pad[f_box_content_pad.length-1];
else 
	wk_content_pad = f_box_content_pad[i3]; 
}


// Now append new divs with the appropriate CSS decoration
var ndiv, ndiv_park;
	for (i1=0; i1<divs_subset.length;i1++) {  
	ndiv_park=divs_subset[i1];
// This will end up as the innermost node.

// Add any mandatory padding to the contained tag nodes (the child nodes within the inner div)

// Get list of all siblings immediately below the inner div - probably <img> tags
i4 = 0;
if (divs_subset[i1].hasChildNodes) {
// now loop around all children of this <div> looking for those with qualifying tag names
// For each qualifying child, set padding to the user's override value
// We need later to take height, width	etc from one of them, so arbitrarily select the first to qualify!
// Note: use a child[] array to avoid the usual 'objects are by reference' assignment issue
// Note finally that the DOM tree has children for comments etc etc

// Find the qualifying tag for this div class
wk_tag = default_tag;
if(typeof(f_box_content_tag) !== "undefined") {
	if(f_box_content_tag.length <= i3)
	// note that tags retrieved (later) using object.tagName are n upper case, so...
		wk_tag = f_box_content_tag[f_box_content_tag.length-1].toUpperCase();
	else 
		wk_tag = f_box_content_tag[i3].toUpperCase(); 
}

if (wk_tag == "notag") tag_none = true; else tag_none = false;

if (tag_none == false) {    // caller has given us a tag to try to match
	child[i4] = divs_subset[i1].firstChild;
	tag_mtch = false;
	do {

			if (child[i4].tagName == wk_tag) { 
				 child[i4].style.padding = wk_content_pad;
				 i5 = i4;  // index of first tagName to qualify
				 tag_mtch = true; // we have a match
			 
			}
   
	   child[i4+1] = child[i4].nextSibling; 
	   i4++; 
	   }
	while (tag_mtch == false && child[i4] != null);
} // ends tag_none == false bracket
} // ends hasChildNodes bracket

if (tag_mtch == false) tag_none = true; // i.e. either no match or the user didn't give a tag

// check whether user wants new divs attributes to be patterned on the class div or its content 
attrib_srce = default_attrib_source;
if(typeof(f_box_attrib_srce) !== "undefined") {
	if(f_box_attrib_srce.length <= i3) 
		attrib_srce = f_box_attrib_srce[f_box_attrib_srce.length-1];
	else 
		attrib_srce = f_box_attrib_srce[i3]; 
}

// assign the correct attribute pattern object 
if (attrib_srce == "content" && tag_none == false) // i.e. we have a child tag found 
	attrib_srce_object = child[i5];
else
	attrib_srce_object = ndiv_park;

// Now make a note of the physical size parameters of this future innermost div or other tag
// because we want to make the inserted divs fit this and not the containing div.
// We use Moz and IE literals as well as Other to help diagnose faults
browser_css_level = "Other";

// see if any margin overrides were specified as a workaround to FFox's inability to handle margin:auto correctly
// FFox converts margin:auto to margin:0 even when the size of the inner element is not 'overconstrained'
// AND larger than the containing block
wk_margin = wk_margin_default;	
if(typeof(f_box_margin) !== "undefined") {
	if(f_box_margin.length <= i3) 
		wk_margin = f_box_margin[f_box_margin.length-1];
	else 
		wk_margin = f_box_margin[i3]; 
}

if(window.getComputedStyle) {
	browser_css_level = "Moz";
	idiv_height = window.getComputedStyle(attrib_srce_object,null).height; 
	idiv_width = window.getComputedStyle(attrib_srce_object,null).width;
	
	// getComputedStyle does not return anything from shorthand css attributes like 'margin' and 'padding'
	// we have to ask for individual longhand attributes 
	idiv_pad_left = window.getComputedStyle(attrib_srce_object,null).paddingLeft;
	idiv_pad_right = window.getComputedStyle(attrib_srce_object,null).paddingRight;
	idiv_pad_top = window.getComputedStyle(attrib_srce_object,null).paddingTop;
	idiv_pad_bottom = window.getComputedStyle(attrib_srce_object,null).paddingBottom;
	idiv_margin_top = window.getComputedStyle(attrib_srce_object,null).marginTop;
	idiv_margin_bottom = window.getComputedStyle(attrib_srce_object,null).marginBottom;
	idiv_float = window.getComputedStyle(attrib_srce_object,null).cssFloat;
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// at this point, idiv_margin left or right is returning 0px with FFox, whereas in the IE code below they return 'auto'
	// and this is even with classdiv specified and everything up to now is consistent with this! So...
	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	if (wk_margin == "auto"){
		idiv_margin_left = "auto";
		idiv_margin_right = "auto";
	}
	else
	{
		idiv_margin_left = window.getComputedStyle(attrib_srce_object,null).marginLeft;
		idiv_margin_right = window.getComputedStyle(attrib_srce_object,null).marginRight;
	}
		
}
else
	if (attrib_srce_object.currentStyle) {
	browser_css_level = "IE";
	idiv_height = attrib_srce_object.currentStyle.height; 
	idiv_width = attrib_srce_object.currentStyle.width;
	
	// See note above. And even though currentStyle is believed to work with shorthand css attributes,
	// continue to use longhand ones for consistency with Moz
	idiv_pad_left = attrib_srce_object.currentStyle.paddingLeft;
	idiv_pad_right = attrib_srce_object.currentStyle.paddingRight;
	idiv_pad_top = attrib_srce_object.currentStyle.paddingTop;
	idiv_pad_bottom = attrib_srce_object.currentStyle.paddingBottom;
	idiv_margin_left = attrib_srce_object.currentStyle.marginLeft;
	idiv_margin_right = attrib_srce_object.currentStyle.marginRight;
	idiv_margin_top = attrib_srce_object.currentStyle.marginTop;
	idiv_margin_bottom = attrib_srce_object.currentStyle.marginBottom;
	idiv_float = attrib_srce_object.currentStyle.cssFloat;
	
	}

// DOM does not let use replace a node with another node so replace the first child of its parent instead! This will give the outermost div. 
// Note that lines are in outer divs and corners in inner divs so that corners will overlay lines (inner divs overlay outer divs)

// Now allow several classes to share the same css images and padding if necessary 

if(typeof(f_box_css_prefix) == "undefined")  // note ==  equates when undefined or null
	alert("Error in fancy_box.js - No prefix for style sheets specified");
	
if(f_box_css_prefix.length <= i3) 
	wk_css_prefix = f_box_css_prefix[f_box_css_prefix.length-1];
else
	wk_css_prefix = f_box_css_prefix[i3]; 

// Find the background colour if specified - or transparent
color = default_color;  
if(typeof(f_box_color) !== "undefined") {
if(f_box_color.length <= i3) 
	color = f_box_color[f_box_color.length-1];
else 
	color = f_box_color[i3]; 
}

// sides then corners or just corners ?
wk_sides_also = default_sides_also; 
if(typeof(f_box_sides_also) !== "undefined") 
{
	if(f_box_sides_also.length <= i3) 
		wk_sides_temp = f_box_sides_also[f_box_sides_also.length-1];
	else 
		wk_sides_temp = f_box_sides_also[i3]; 
	
	if(wk_sides_temp == "yes") wk_sides_also = true;
	else
	if (wk_sides_temp == "no") wk_sides_also = false;
	else
	wk_sides_also = default_sides_also; 
}
	

i2 = 0;
ndiv=document.createElement("div");
ndiv_park.parentNode.replaceChild(ndiv,ndiv_park);
attrib_set(); // call function
// this becomes the outer div - the div defining the background (or transparent)





// sides then corners or just corners ?
if(wk_sides_also == true)
	i6 = 1; 
else 
	i6 = 5;
//Now the remaining eight divs

for (i2 = i6; i2<9; i2++) {
	ndiv_park=ndiv;
	ndiv=document.createElement("div");
	ndiv_park.appendChild(ndiv);
	attrib_set(); // call function
} // closes i2 loop

// Finally, replace the original div as the child of the last appended div
// so that it becomes the inner div
ndiv.appendChild(divs_subset[i1]); 

// Make sure any CSS background does not obscure the container divs
divs_subset[i1].style.backgroundColor = "transparent"; 
} // closes i1 loop
} // closes i3 loop
} // closes function