function init() {
	init_layout();
	remove_iw_toolbar();

	dojo.addOnLoad(function() {
		if ($is_widget.toLowerCase() == 'true') {
			// fix button background
			dojo.query(".dijitButtonNode").forEach(function(node) {
				if (node.firstChild.id == "sf_button") {

					node.style.display = "none";
					node.parentNode.style.backgroundRepeat = "no-repeat";
					node.parentNode.style.width = "154px";
					node.parentNode.style.height = "35px";
					node.parentNode.style.cursor = "pointer";
					node.parentNode.style.margin = "0";
					dojo.connect(node.parentNode, "onclick", function() {
						dijit.byId("service_finder").show();
					});

					if (dojo.byId("sf-button") != null) {
						dojo.place(node.parentNode, "sf-button", "replace");
					}

				}
				else {
					node.style.backgroundImage = "none";
					node.style.backgroundColor = "#dc9e1d";
					dojo.connect(node, "onclick", function() {
						var i = 0;
						node.style.backgroundColor = "#cc8e0d";
					});
					dojo.connect(node, "onmouseover", function() {
						var i = 0;
						node.style.backgroundColor = "#d49615";
					});
					dojo.connect(node, "onmouseout", function() {
						var i = 0;
						node.style.backgroundColor = "#dc9e1d";
					});
				}
			});

			dojo.query(".dijitDialog .closeText").forEach(function(node) {
				node.innerHTML = "Close";
				node.title = "Close";
				node.alt = "Close";
			});

			// If DB is unavailable replace the link to popup with a link to static a-z page
			if (dojo.byId("sf_error") != null) {
				var button = dojo.byId("sf_button");
				dojo.place("<a href=" + $errorpage + "><img src='/common/images/services_forms.gif'/></a>", button.parentNode.parentNode, "after");
				button.parentNode.parentNode.parentNode.removeChild(button.parentNode.parentNode);
			}

			if (dojo.isIE) {
				if (dojo.isIE <= 6.0) {
					dojo.query(".claro .dijitDialogCloseIcon").forEach(function(node) {
						var i = 0;
						node.style.backgroundImage = "none";
					});
				}

				// shadows - causing positioning issues with cursor
				// dojo.byId("service_finder").style.filter = "progid:DXImageTransform.Microsoft.shadow(color='#444444', Direction=45,  Strength=15), progid:DXImageTransform.Microsoft.shadow(color='#444444', Direction=135,  Strength=15), progid:DXImageTransform.Microsoft.shadow(color='#444444', Direction=225,  Strength=15), progid:DXImageTransform.Microsoft.shadow(color='#444444', Direction=315,  Strength=15)";
			}	
		}
		else {
			dojo.style(dojo.byId("service_finder"), "display", "block");
		}
	});

	select(dojo.byId("sf_filter_srv"));
	init_content();
}

function remove_iw_toolbar() {
	if (dojo.query("iw_vpreview_toolbar")) {
		dojo.query("#iw_vpreview_toolbar").style("display", "none");
		dojo.query("#iw_vpreview_menu_iframe").style("display", "none");
	}
}

function init_layout() {
	dojo.addClass(dojo.body(), "claro");
	if ($is_widget.toLowerCase() == 'true') {
		//dojo.style(dojo.byId("sf_button"), "display", "block");
		dojo.style(dojo.byId("service_finder"), "display", "none");
		dojo.query('[widgetid = "sf_button"]').style("display", "block");
	}

	dojo.style(dojo.byId("sf_filter_srv"), "background", "url('/local/gov/images/services_finder/fltr_sel.jpg') no-repeat scroll 0 0 transparent");
	dojo.query("#sf_filter_srv span").style("color", "white");
	dojo.style(dojo.byId("sf_filter_frm"), "background", "url('/local/gov/images/services_finder/fltr_def.jpg') no-repeat scroll 0 0 transparent");
	dojo.query("#sf_filter_frm span").style("color", "#234075");
	dojo.style(dojo.byId("sf_filter_mns"), "background", "url('/local/gov/images/services_finder/fltr_def.jpg') no-repeat scroll 0 0 transparent");
	dojo.query("#sf_filter_mns span").style("color", "#234075");

	//dojo.query("#sf_search_submit").style("color", "white");
	//dojo.query("#sf_search_submit").style("background", "#e3a82b none");
	//dojo.query("#sf_loc_submit").style("color", "white");
	//dojo.query("#sf_loc_submit").style("background", "#e3a82b none");
	
	// fix browsers anomalies
	if ($is_widget.toLowerCase() == 'true') {
		if (dojo.isIE <= 7.0) {
			dojo.style(dojo.byId("sf_filter_list"), "marginLeft", "-145px");
			//dojo.style(dojo.byId("sf_search_label"), "position", "static");
		}
		
		//dojo.style(dojo.byId("service_finder"), "fontSize", "1em");
	}

	if (dojo.isIE == 6.0) {
		//dojo.style(dojo.byId("sf_search"), "marginTop", "-8px");
	}
	else 
	if (dojo.isIE == 7.0) {
		//dojo.style(dojo.byId("sf_search"), "marginBottom", "8px");
		//dojo.style(dojo.byId("sf_search_label"), "marginTop", "5px");
	}
	else 
	if (dojo.isFF >= 3.0) {
		//dojo.style(dojo.byId("sf_search"), "marginTop", "1px");
	}

	dojo.place("sf_list", "sf_browser", "last");
	dojo.place("slide", "sf_browser", "last");
	dojo.byId("slide").innerHTML = "";
}

function init_content() {
	var o1 = new Object();
	o1.name = "Services";
	o1.parameters = dojo.queryToObject("content_type=service");
	o1.id = "services";
	o1.content = "Loading ...";
	o1.selected = true;

	var o2 = new Object();
	o2.name = "Forms";
	o2.parameters = dojo.queryToObject("content_type=form");
	o2.id = "forms";
	o2.content = "Loading ...";
	o2.selected = false;

	var o3 = new Object();
	o3.name = "Ministries";
	o3.parameters = dojo.queryToObject("category_type=ministry&content_type=service|form");
	o3.id = "ministries";
	o3.content = "Loading ...";
	o3.selected = false;

	var tabs = [o1, o2, o3];

	switchBreadcrumb("");
	initBreadcrumb(tabs);

	dojo.forEach(tabs, function(tab) {
		populateData(tab);
	});

	//Breadcrumb trigger
	dojo.query("#sf_filter_list li").forEach(function(node, index, arr) {
		//console.debug(node.innerHTML);
		dojo.connect(node,"onclick",function() {
			switchBreadcrumb(this.firstChild.innerHTML.toLowerCase());
		});
	});

	//console.debug($service_url);
}

function initBreadcrumb(tabs) {
	dojo.byId("sf_breadcrumbs_list").innerHTML = "";
	dojo.forEach(tabs, function(tab) {
		var ul = dojo.doc.createElement("ul");
		ul.setAttribute("id", "bc_" + tab.id);
		dojo.addClass(ul, 'crumbs');
		if (tab.selected != true) {
			dojo.style(ul, {"display": 'none'});
		}
		dojo.byId("sf_breadcrumbs_list").appendChild(ul);
	});
}

function switchBreadcrumb(tabid) {
	dojo.query("div#sf_breadcrumbs_list > ul").forEach(function(node, index, arr) {
		if (node.id == "bc_" + tabid) {
			dojo.style(node, {"display": 'inline'});
		}
		else{
			dojo.style(node, {"display": 'none'});
		}
	});
}

function createBreadcrumb(item) {
	var li = dojo.doc.createElement("li");
	var link = dojo.doc.createElement("span");
	dojo.addClass(link, 'breadcrumbs_section');
	link.setAttribute("href", "#");
	var text = item.name;
	var crumb_limit = 20;
	if (text.length > crumb_limit) {
		var pos = getTruncatePos(text, crumb_limit);
		if (pos < text.length) {
			text = text.substr(0, pos) + " ...";
			link.setAttribute("title", item.name);
		}
	}
	if (dojo.byId("bc_" + item.id).children.length == 0) {
		link.innerHTML = "<span class='breadcrumbs_text'>" + text + "</span>";
	}
	else {
		link.innerHTML = "&rsaquo; " + "<span class='breadcrumbs_text'>" + text + "</span>";
	}
	link._connectHandlers = [];

	link._connectHandlers.push(dojo.connect(link , "onclick", function() {
		dojo.query('ul#bc_' + item.id + ' > li:last-child > span').forEach(function(node, index, arr) {
			if (link != node) {
				populateData(item, link);
			}
		});
	}));
	
	link._connectHandlers.push(dojo.connect(link, "onmouseover", function() {
		dojo.query('ul#bc_' + item.id + ' > li:last-child > span').forEach(function(node, index, arr) {
			if (link != node) {
				dojo.style(link, "cursor", "pointer");
				dojo.style(link, "color", "#606060");
			}
		});
	}));

	link._connectHandlers.push(dojo.connect(link, "onmouseout", function() {
		dojo.query('ul#bc_' + item.id + ' > li:last-child > span').forEach(function(node, index, arr) {
			dojo.style(link, "color", "#404040");
		});
	}));

	li.appendChild(link);
	dojo.byId("bc_" + item.id).appendChild(li);
	
	updateUnderlines('ul#bc_' + item.id);
}

function removeBreadcrumb(input, item) {
	var found = false;
	dojo.query('li > span', dojo.byId('bc_' + input.id)).forEach(function(node, index, arr) {
		if (node && node.parentNode && found == true) {
			release(dojo.byId('bc_' + input.id).removeChild(node.parentNode));
		}

		if (node == item) {
			found = true;
		}
	});
	
	updateUnderlines('ul#bc_' + input.id);
}

function updateUnderlines(node_id) {
	var node = dojo.query(node_id)[0];
	var num = node.children.length;
	for (i=0; i<num-1; ++i) {
		dojo.style(node.children[i].children[0].children[0], "textDecoration", "underline");
	}
	dojo.style(node.children[num-1].children[0].children[0], "textDecoration", "none");
}

function getTruncatePos(str, limit) {
	var maxLen = Math.min(str.length, limit + 10);
	var chars = [" ", ",", ")", "/"];
	var temp, pos = maxLen;
	for (i=0; i<chars.length; ++i) {
		temp = str.indexOf(chars[i], limit);
		if (temp > -1) {
			pos = Math.min(pos, temp);
		}
	}

	return pos;
}

function select(filter) {
	dojo.query("#sf_filter_list li").forEach(function(node){
		if (node == filter) {
			dojo.style(node, "background", "url('/local/gov/images/services_finder/fltr_sel.jpg') no-repeat");
			dojo.style(node.firstChild, "color", "white");
			dojo.style(node, "height", "50px");
			dojo.style(node, "width", "92px");
			dojo.style(node, "lineHeight", "50px");
			dojo.style(node, "marginTop", "+5px");
			dojo.style(node, "zIndex", "1");
			dojo.attr(node, "selected", "true");
		}
		else {
			dojo.style(node, "background", "url('/local/gov/images/services_finder/fltr_def.jpg') no-repeat");
			dojo.style(node.firstChild, "color", "#234075");
			dojo.style(node, "height", "50px");
			dojo.style(node, "width", "92px");
			dojo.style(node, "lineHeight", "50px");
			dojo.style(node, "marginTop", "+5px");
			dojo.style(node, "zIndex", "0");
			dojo.attr(node, "selected", "false");
		}
	});
	
	var active_id = filter.lastChild.innerHTML.toLowerCase();
	dojo.query("#sf_list div").forEach(function(node){
		if (node.id == active_id) {
			dojo.style(dojo.byId(node.id), "display", "block");
			dojo.attr(dojo.byId(node.id), "visible", "true");
		}
		else {
			dojo.style(dojo.byId(node.id), "display", "none");
			dojo.attr(dojo.byId(node.id), "visible", "false");
		}
	});
}

function selected(filter) {
	if (dojo.attr(filter, "selected") == "true") {
		return 1;
	}
	else {
		return 0;
	}
}

function hover(filter) {
	if (!selected(filter)) {
		dojo.style(filter, "cursor", "pointer");
	}
	else {
		dojo.style(filter, "cursor", "default");
	}
}

function unhover(filter) {
	if (!selected(filter)) {
		dojo.style(filter, "cursor", "default");
	}
}

function populateData(input, removeBcLink) {
	//console.log("parameters:" + input.parameters);
	var drilldown = true;
	if (removeBcLink != undefined) {
		drilldown = false;
	}
	dojo.xhrGet({
		url: $service_url,
		handleAs: "json",
		//sync: true,
		content: input.parameters,
		load: function(data, ioArgs) {
			//console.dir(data);
			if (data.type == 'category') {
				createCatList(input, data, drilldown);
			}
			else if (data.type == 'content') {
				createConList(input, data, drilldown);
			}
			else if (data.type == 'dcr') {
				createDCR(input, data, drilldown);
			}
			else if (data.type == 'error') {
				createErrMsg(input, data);
			}

			if (data.type != 'error') {
				//Create / Remove breadcrumb
				if (removeBcLink != undefined) {
					removeBreadcrumb(input, removeBcLink);
				}
				else{
					createBreadcrumb(input);
				}
			}
		},
		error: function(err, ioArgs) {
			// again, ioArgs is useful, but not in simple cases
			//alert("Error loading data.\nPossible reason: 'Target' parameter is not set properly.");
			//console.error(err); // display the error
		}
	});
}

function createErrMsg(input, data) {
	if (dojo.byId("sf_error") == null) {
		release(dojo.byId("sf_top"));
		release(dojo.byId("sf_mid"));
		release(dojo.byId("sf_bot"));
		dojo.place("<div id='sf_error'> \
					Our apologies.<br/> \
					Government Services Finder is unavailable at the moment.<br/> \
					While we are working to resolve the issue you can visit <a href=" + $errorpage + ">this page</a> to see a list of government services. \
					</div>", "sf_bot", "after");
		dojo.byId("sf_top").parentNode.removeChild(dojo.byId("sf_top"));
		dojo.byId("sf_mid").parentNode.removeChild(dojo.byId("sf_mid"));
		dojo.byId("sf_bot").parentNode.removeChild(dojo.byId("sf_bot"));
	}
}

function getTable(input, data, cols) {
	// ignore categories with 0 items
	var items = [];
	var len = 0;
	for (var i=0; i<data.results.length; ++i) {
		if ((data.results[i].count == undefined) || (data.results[i].count > 0)) {
			items[len] = data.results[i];
			++len;
		}
	}

	//var items = data.results;
	var num = items.length;
	var sec_col_start = 1 + Math.floor((num - 1) / cols);
	
	var table = dojo.doc.createElement("table");
	dojo.addClass(table, 'list-tbl');
	var tbody = dojo.doc.createElement("tbody");
	
	for(var i=0; i<sec_col_start; i++) {
		(function(i) {
			var tr = dojo.doc.createElement("tr");
			var td = dojo.doc.createElement("td");
			var span = dojo.doc.createElement("span");
			span._connectHandlers = [];
			dojo.addClass(span, 'item');
			
			// left col
			span.innerHTML = "<span class='item_name'>" + items[i].name + "</span>";
			if (data.type == "category") {
				span.innerHTML = span.innerHTML + " (" + items[i].count + ")";
			}
			if ((items[i].count == undefined) || (items[i].count > 0)) {
				if (cols > 1) {
					span._connectHandlers.push(dojo.connect(span, "onclick", function() {
						items[i].id = input.id;
						populateData(items[i]);
					}));
				}
				else { // cols == 1
					var detailsURL = $detailspage + dojo.objectToQuery(items[i].parameters);
					span._connectHandlers.push(dojo.connect(span, "onclick", function() {
						window.location.href = detailsURL;
					}));
				}
				span._connectHandlers.push(dojo.connect(span, "onmouseover", function() {
					dojo.style(span, "cursor", "pointer");
					dojo.style(span, "color", "#606060");
				}));
				span._connectHandlers.push(dojo.connect(span, "onmouseout", function() {
					dojo.style(span, "color", "#404040");
				}));
			}
			td.appendChild(span);
			tr.appendChild(td);

			if (sec_col_start < num) {
				// right col
				var td2 = dojo.doc.createElement("td");
				var span2 = dojo.doc.createElement("span");
				span2._connectHandlers = [];
				dojo.addClass(span2, 'item');
				var i2 = sec_col_start + i;
				if (i2 < num) {
					span2.innerHTML = "<span class='item_name'>" + items[i2].name + "</span>";
					if (data.type == "category") {
						span2.innerHTML = span2.innerHTML + " (" + items[i2].count + ")";
					}
					if ((items[i2].count == undefined) || (items[i2].count > 0)) {
						span2._connectHandlers.push(dojo.connect(span2, "onclick", function() {
							items[i2].id = input.id;
							populateData(items[i2]);
						}));
						span2._connectHandlers.push(dojo.connect(span2, "onmouseover", function() {
							dojo.style(span2, "cursor", "pointer");
							dojo.style(span2, "color", "#606060");
						}));
						span2._connectHandlers.push(dojo.connect(span2, "onmouseout", function() {
							dojo.style(span2, "color", "#404040");
						}));
					}
				}
				td2.appendChild(span2);
				tr.appendChild(td2);
			}

			tbody.appendChild(tr);
		}(i));
	}
	
	table.appendChild(tbody);
	
	return table;
}

function createCatList(input, data, drilldown) {
	var pane = dojo.byId(input.id);
	var toSlide = false;
	var current_elem;
	if (pane.innerHTML.toLowerCase() != input.id) {
		toSlide = true;
		var num = dojo.byId(input.id).children.length;
		current_elem = dojo.doc.createElement(dojo.byId(input.id).nodeName);
		current_elem.innerHTML = dojo.byId(input.id).innerHTML;
		current_elem = current_elem.firstChild;
	}
	else {
		dojo.byId(input.id).innerHTML = "";
	}

	var table = getTable(input, data, 2);

	if (toSlide) {
		var table2 = getTable(input, data, 2);
		slide(current_elem, table2, pane/*.scrollTop*/, drilldown);
	}

	dojo.byId(input.id).innerHTML = "";
	dojo.byId(input.id).appendChild(table);
	dojo.byId(input.id).scrollTop = 0;
}

function createConList(input, data, drilldown) {
	var pane = dojo.byId(input.id);
	var toSlide = false;
	var current_elem;
	if (pane.innerHTML != "Loading ...") {
		toSlide = true;
		var num = dojo.byId(input.id).children.length;
		current_elem = dojo.doc.createElement(dojo.byId(input.id).nodeName);
		current_elem.innerHTML = dojo.byId(input.id).innerHTML;
		current_elem = current_elem.firstChild;
	}

	var table = getTable(input, data, 1);

	if (toSlide) {
		var table2 = getTable(input, data, 1);
		slide(current_elem, table2, pane/*.scrollTop*/, drilldown);
	}

	dojo.byId(input.id).innerHTML = "";
	dojo.byId(input.id).appendChild(table);
}

function slide(current_elem, new_node, active_pane, drilldown) {
	var clone = dojo.clone(new_node);
	if ((dojo.isIE) && (clone.tagName.toLowerCase() != "table")) {
		clone.innerHTML = new_node.innerHTML;
	}

	var scrollTop = active_pane.scrollTop;
	
	var slide = dojo.byId("slide");
	var leftslide = dojo.doc.createElement("div");
	dojo.attr(leftslide, "id", "leftslide");
	var rightslide = dojo.doc.createElement("div");
	dojo.attr(rightslide, "id", "rightslide");
	slide.appendChild(leftslide);
	slide.appendChild(rightslide);

	var one_width = active_pane.parentNode.clientWidth;
	var leftOffset = active_pane.parentNode.offsetLeft;
	dojo.style(slide, "height", active_pane.parentNode.clientHeight + "px");
	dojo.style(slide, "width", 2 * one_width + "px");

	if (drilldown) {
		dojo.byId("leftslide").appendChild(current_elem);
		release(dojo.byId("rightslide"));
		dojo.byId("rightslide").appendChild(clone);
		slidePane(slide, leftOffset, leftOffset-one_width, 1000, active_pane);
	}
	else {
		dojo.byId("rightslide").appendChild(current_elem);
		release(dojo.byId("leftslide"));
		dojo.byId("leftslide").appendChild(clone);
		if (dojo.byId("rightslide").innerHTML != dojo.byId("leftslide").innerHTML) {
			slidePane(slide, leftOffset-one_width, leftOffset, 1000, active_pane);
		}
	}
}

function slidePane(slide_pane, from, to, dur, active_pane) {
		var position;
		var slideArgs = {
			node: slide_pane,
			duration: dur,
			properties: {
				left: {
					end: to,
					units: "px"
				}
			},
			beforeBegin: function() {
				var scrollTop = active_pane.scrollTop;
				var fromSlide, toSlide;
				if (to > from) {
					fromSlide = slide_pane.children[1];
					toSlide = slide_pane.children[0];
				}
				else {
					fromSlide = slide_pane.children[0];
					toSlide = slide_pane.children[1];
				}
				dojo.style(slide_pane, {left: "-10000px"});
				dojo.style(slide_pane, "display", "block");
				fromSlide.scrollTop = scrollTop;
				dojo.style(active_pane.parentNode, "display", "none");
				dojo.style(slide_pane, {left: from + "px"});
				toSlide.scrollTop = 0;
				position = dojo.coords(slide_pane.id, false);
				slideArgs.properties.left.start = position.l; 
			},
			onEnd: function() {
				dojo.style(slide_pane, "display", "none");
				dojo.style(active_pane.parentNode, "display", "block");
				active_pane.scrollTop = 0;
				release(slide_pane);
			}
		};
		dojo.animateProperty(slideArgs).play();
}

function release(node) {
	//if (node.children.length > 0) {
	if (node.children) {
		dojo.forEach(node.children, release);
	}

	if ((!node.children) && (node.childNodes)) {
		dojo.forEach(node.childNodes, release);
	}

	if (node._connectHandlers != undefined) {
		dojo.forEach(node._connectHandlers, function(handler) {
			dojo.disconnect(handler);
		});
	}

	if (node._newedObjects != undefined) {
		dojo.forEach(node._newedObjects, function(object) {
			delete object;
		});
	}

	if ((dojo.isSafari) && (node.tagName.toUpperCase() == "IMG")) {
		dojo.destroy(node);
		return;
	}

	dojo.empty(node);
}
