function formValidationHandler(formNode, validators)
	{
		ShippingAdvisor.clearValidateIcons(formNode);
		// create overlays for each failed validation
		for (var i in validators)
		{
			var el = document.createElement('img');
			el.setAttribute('src', '/static/images/shipping/exclamation.png');
			el.setAttribute('class', 'validateFailedIcon');
			YAHOO.util.Dom.insertAfter(el, formNode[validators[i].name]);
			new YAHOO.widget.Tooltip("tooltip-" + validators[i].name, {
				context:el,
				text:validators[i].message,
				showDelay:0,
				hideDelay:0
			});
		}
		
	}
YAHOO.util.Event.onDOMReady(function () {	
	ShippingAdvisor = new function ()
	{
		
		this.actionsType = 'standard';
		this.toolTipIndex = 0;
		this.validateOverlays = new Array();
		
		// REMINDER FUNCTIONS
		
		this.cachedReminders = new Array();
		this.currentReminderIndex = 0;
		this.reminderWindowOpen = false;
		
		this.openReminderWindow = function()
		{
			if (!ShippingAdvisor.reminderWindowOpen)
			{
				ShippingAdvisor.reminderWindow = new YAHOO.widget.Overlay("reminderWindow",{
					context:["content", "tl", "tl"],
					width:'100%'
				});
				ShippingAdvisor.reminderWindow.setBody('<div id="reminderWindowPrev" class="reminderWindowButton"></div><div id="reminderWindowNext" class="reminderWindowButton"></div><div id="reminderWindowBody"></div>');
				ShippingAdvisor.reminderWindow.render(YAHOO.util.Dom.get('content'));
				ShippingAdvisor.reminderWindow.show();
				
				var height = 30;
				var bodyEl = YAHOO.util.Dom.get('reminderWindowBody');
				var anim = new YAHOO.util.Anim(YAHOO.util.Dom.get('reminderWindow'), {opacity: {from: 0, to: 1 }}, 1, YAHOO.util.Easing.easeOut);
				anim.animate();
				
				ShippingAdvisor.reminderWindowOpen = true;
				return bodyEl;
			}
			else
			{
				return YAHOO.util.Dom.get('reminderWindowBody');
			}
			
			
		}
		
		this.closeReminderWindow = function()
		{
			var bodyEl = YAHOO.util.Dom.get('reminderWindow');
			var anim = new YAHOO.util.Anim(bodyEl, {opacity: {to: 0 }}, 1, YAHOO.util.Easing.easeIn);
			anim.onComplete.subscribe(function(e) {
				ShippingAdvisor.reminderWindow.hide();
			});
			anim.animate();
			var anim = new YAHOO.util.Anim("content", {paddingTop: {to: 0 }}, 1.2, YAHOO.util.Easing.easeOut);
			anim.animate();
			ShippingAdvisor.reminderWindowOpen = false;
		}
		
		this.retrieveNextReminder = function(successCallback)
		{
			var callback = {
				success: function (o) {
					var obj = YAHOO.lang.JSON.parse(o.responseText);
					if (obj.reminder)
					{
						ShippingAdvisor.cachedReminders.push(obj.reminder);
						ShippingAdvisor.totalReminders = obj.totalReminders;
						if (successCallback)
						{
							successCallback();
						}
					}
					
				}
			};
			var postData = "";
			if (ShippingAdvisor.cachedReminders.length > 0)
			{
				postData += "reminderID=" + ShippingAdvisor.cachedReminders[ShippingAdvisor.currentReminderIndex].ID;
			}
			ShippingAdvisor.ajaxRequest("POST", "ajax/getNextReminder.ajax", callback, postData);
		}
		
		this.nextReminder = function()
		{
			var showReminder;
			
			if (ShippingAdvisor.cachedReminders.length == 0)
			{
				// no reminders cached yet
				ShippingAdvisor.retrieveNextReminder(function(){
					ShippingAdvisor.showReminder(ShippingAdvisor.cachedReminders[ShippingAdvisor.currentReminderIndex]);
				});
			}
			else if (ShippingAdvisor.cachedReminders.length > (ShippingAdvisor.currentReminderIndex+1))
			{
				// we've already cached the next reminder
				ShippingAdvisor.currentReminderIndex++;
				ShippingAdvisor.showReminder(ShippingAdvisor.cachedReminders[ShippingAdvisor.currentReminderIndex]);
			}
			else
			{
				// we need to get the next reminder
				
				ShippingAdvisor.retrieveNextReminder(function(){
					ShippingAdvisor.currentReminderIndex++;
					ShippingAdvisor.showReminder(ShippingAdvisor.cachedReminders[ShippingAdvisor.currentReminderIndex]);
				});
			}
		}
		
		this.prevReminder = function()
		{
			if ((ShippingAdvisor.currentReminderIndex-1) >= 0)
			{
				ShippingAdvisor.currentReminderIndex--;
				ShippingAdvisor.showReminder(ShippingAdvisor.cachedReminders[ShippingAdvisor.currentReminderIndex]);
			}
		}
		
		this.deferReminder = function(reminder)
		{
			var amount = (+YAHOO.util.Dom.get('reminderDeferAmount').value);
			if (!YAHOO.lang.isNumber(amount) || amount <= 0)
			{
				ShippingAdvisor.displayAlert('Please enter a valid amount.');
				YAHOO.util.Dom.get('reminderDeferUnit').selectedIndex = 0;
				return;
			}
			var callback = {
				success:function(o)
				{
					var obj = YAHOO.lang.JSON.parse(o.responseText);
					ShippingAdvisor.totalReminders = obj.totalReminders;
					ShippingAdvisor.removeCachedReminder(reminder);
					
				}
			};
			ShippingAdvisor.ajaxRequest("POST", "ajax/deferReminder.ajax", callback, YAHOO.util.Connect.setForm("reminderDeferForm") + "&reminderID=" + reminder.ID);
			
		}
		
		this.showReminder = function(reminder)
		{
			var bodyEl = ShippingAdvisor.openReminderWindow();
			bodyEl.innerHTML = '<div id="reminderWindowButtons"><form id="reminderDeferForm" style="display:inline">Remind me in: <input type="text" id="reminderDeferAmount" name="amount"/> <select id="reminderDeferUnit" name="unit"><option value="">Select...</option><option value="hours">Hours</option><option value="days">Days</option><option value="months">Months</option></select></form> or <input type="button" value="Dismiss" id="reminderDismissButton" /></div>';
			
			if (ShippingAdvisor.currentReminderIndex > 0)
			{
				YAHOO.util.Dom.get('reminderWindowPrev').innerHTML = '<a href="#" onClick="ShippingAdvisor.prevReminder();return false;"><<' + ShippingAdvisor.currentReminderIndex + ' more</a>';
				bodyEl.style.marginLeft = '65px';
			}
			else
			{
				YAHOO.util.Dom.get('reminderWindowPrev').innerHTML = '';
				bodyEl.style.marginLeft = '0px';
			}
			if (ShippingAdvisor.currentReminderIndex < (ShippingAdvisor.totalReminders - 1))
			{
				YAHOO.util.Dom.get('reminderWindowNext').innerHTML = '<a href="#" onClick="ShippingAdvisor.nextReminder();return false;">' + (ShippingAdvisor.totalReminders - (ShippingAdvisor.currentReminderIndex+1)) + ' more >> </a>';
			}
			else
			{
				YAHOO.util.Dom.get('reminderWindowNext').innerHTML = '';
			}
			
			bodyEl.innerHTML += reminder.reminderText;
			
			if (bodyEl.scrollHeight < 30)
			{
				bodyEl.style.height = '30px';
			}
			
			var anim = new YAHOO.util.Anim("content", {paddingTop: {to: bodyEl.scrollHeight+13 }}, .2, YAHOO.util.Easing.easeOut);
			anim.animate();
					
			new YAHOO.widget.Button("reminderDismissButton", {
				label:"Dismiss"
			}).addListener("click", function (e, reminder) {
				ShippingAdvisor.dismissReminder(reminder);
			}, reminder);
			
			YAHOO.util.Event.addListener('reminderDeferUnit','change', function (e) {
				ShippingAdvisor.deferReminder(reminder);
			}, reminder);
		}
		
		this.dismissReminder = function(reminder)
		{
			var callback = {
				success:function(o)
				{
					var obj = YAHOO.lang.JSON.parse(o.responseText);
					ShippingAdvisor.totalReminders = obj.totalReminders;
					ShippingAdvisor.removeCachedReminder(reminder);
					
				}
			};
			ShippingAdvisor.ajaxRequest("POST", "ajax/dismissReminder.ajax", callback, "reminderID=" + reminder.ID);
		}
		
		this.removeCachedReminder = function(reminder)
		{
			if (ShippingAdvisor.totalReminders > 0)
					{
						for (var i in ShippingAdvisor.cachedReminders)
						{
							if (ShippingAdvisor.cachedReminders[i] == reminder)
							{
								ShippingAdvisor.cachedReminders.splice(i,1);
							}
						}
						if (ShippingAdvisor.currentReminderIndex > (ShippingAdvisor.cachedReminders.length-1) && ShippingAdvisor.currentReminderIndex > 0)
						{
							ShippingAdvisor.currentReminderIndex = (ShippingAdvisor.cachedReminders.length - 1)
						}
						if (ShippingAdvisor.cachedReminders.length > 0)
						{
							ShippingAdvisor.showReminder(ShippingAdvisor.cachedReminders[ShippingAdvisor.currentReminderIndex]);
						}
						else 
						{
							ShippingAdvisor.nextReminder();
						}
					}
					else
					{
						ShippingAdvisor.cachedReminders = new Array();
						ShippingAdvisor.closeReminderWindow();
						ShippingAdvisor.currentReminderIndex = 0;
					}
		}
		
		// AJAX FUNCTIONS
		
		this.ajaxRequest = function(method, uri, callback, postData)
		{
			var preCallback = {
				success:function(o) {
					try
					{
						var obj = YAHOO.lang.JSON.parse(o.responseText);
						if (obj)
						{
							if (obj.permissionDenied)
							{
								
								if (obj.permissionDenied == 'cookie')
								{
									window.location = '/cms/access/loginPlease.html';
								}
								else if (obj.permissionDenied == 'orderLock')
								{
									ShippingAdvisor.orderLockPanel = new YAHOO.widget.Panel("orderLock", {
											close:false,
											modal:true,
											fixedcenter: true, 
											underlay:"shadow", 
											draggable:false,
									});
									ShippingAdvisor.orderLockPanel.setBody(obj.msg);
									ShippingAdvisor.orderLockPanel.render(document.body);
									ShippingAdvisor.orderLockPanel.show();
									return;
								}
								else
								{
									ShippingAdvisor.displayAlert(obj.msg ? obj.msg : "Insufficient permissions for this action.");
									if (callback && callback.failure)
									{
										callback.failure(o);
									}
									return;
								}
								
							}
							if (obj.events)
							{
								ShippingAdvisor.fireEvents(obj.events);
							}
							if (obj.orderCount)
							{
								ShippingAdvisor.onOrderCountUpdate.fire(obj.orderCount);
							}
							if (obj.msg)
							{
								ShippingAdvisor.displayAlert(obj.msg);
							}
							if (obj.popup)
							{
								ShippingAdvisor.ajaxDialog = new YAHOO.widget.Panel("ajaxDialog",{
									modal:true,
									width:"auto", 
									fixedcenter: true, 
									underlay:"shadow", 
									close:true, 
									visible:false
								});
								ShippingAdvisor.ajaxDialog.setBody(obj.popup);
								ShippingAdvisor.ajaxDialog.render(document.body);
								ShippingAdvisor.ajaxDialog.show();
							}
							
						}
					}
					catch(e)
					{
						if (e instanceof SyntaxError)
						{
							// JSON error, usually means we've passed back HTML instead of JSON
							// do nothing and just pass it through to the callback
						}
					}
					if (callback)
					{
						callback.success(o);
					}
				}
			};
			if (callback)
			{
				preCallback = YAHOO.lang.merge(callback, preCallback);
			}
			// add server refresh time to all ajax requests
			if (postData)
			{
				postData += "&refreshTime=" + ShippingAdvisor.refreshTime;
			}
			else
			{
				postData = "refreshTime=" + ShippingAdvisor.refreshTime;
			}
			YAHOO.util.Connect.asyncRequest(method,uri,preCallback,postData);
		}
		
		this.clearValidateIcons = function(form){
			// clear all validate icons
			var icons = YAHOO.util.Dom.getElementsByClassName('validateFailedIcon', '', form);
			for (var i in icons)
			{
				icons[i].parentNode.removeChild(icons[i]);
			}
			
		}
		
		this.showLoadingWidget = function()
		{
			if (!ShippingAdvisor.loadingWidget)
			{
				ShippingAdvisor.loadingWidget = new YAHOO.widget.Overlay("loadingWidget", 
					{ xy:[450,120], 
					  visible:false, 
					  width:"100px"
				});
				ShippingAdvisor.loadingWidget.setBody('<img src="/static/images/shipping/ajax-loader.gif"/> Loading...');
				ShippingAdvisor.loadingWidget.render(document.body);
			}
			ShippingAdvisor.loadingWidget.show();
		}
		
		this.hideLoadingWidget = function()
		{
			ShippingAdvisor.loadingWidget.hide();
		}
		
		YAHOO.util.Connect.startEvent.subscribe(function(e) {
				
			ShippingAdvisor.showLoadingWidget(); 
			// disable all input fields and buttons
			/*var buttons = document.getElementsByTagName("input");
			for (var i in buttons)
			{
				buttons[i].disabled = true;
			}*/
			
		});
		YAHOO.util.Connect.completeEvent.subscribe(function(e) {
			ShippingAdvisor.hideLoadingWidget(); 
			// enable all input fields and buttons
			/*var buttons = document.getElementsByTagName("input");
			for (var i in buttons)
			{
				buttons[i].disabled = false;	
			}*/
		});
		
		this.requestOrderCount = function() {
			ShippingAdvisor.ajaxRequest("GET", "ajax/getOrderCounts.ajax");
		}
		
		this.updateOrderCount = function(countObject)
		{
			//unshipped orders
			var ordersCountEl = YAHOO.util.Dom.get('orderCount');
			ordersCountEl.innerHTML = '';
			var div = document.createElement('div');
			div.innerHTML = '<table><tr><td id="shippingCountTd"></td><td id="flagsCountTd"></td></tr></table>';
			ordersCountEl.appendChild(div);
			
			var el = YAHOO.util.Dom.get('shippingCountTd');
			var table = document.createElement('table');
			
			var tr = document.createElement('tr');
			new YAHOO.util.Element(tr).addClass((countObject.unshipped.count > 0) ? "orderCountFull" : "orderCountEmpty");
			if (countObject.unshipped.count > 0) 
			{
				YAHOO.util.Event.addListener(tr, "click", function(e) { window.location="shipruns.html"; });
				tr.style.backgroundColor = 'white';
			}
			
			var td1 = document.createElement('td');
			new YAHOO.util.Element(td1).addClass("orderCountTitle");
			td1.innerHTML = 'Unshipped:';
			var td2 = document.createElement('td');
			new YAHOO.util.Element(td2).addClass("orderCountNumber");
			td2.innerHTML = countObject.unshipped.count;
			if (countObject.unshipped.conflict > 0)
			{
				td2.style.color = '#ff0000';
			}
			
			tr.appendChild(td1);
			tr.appendChild(td2);
			
			table.appendChild(tr);
			
			var tr = document.createElement('tr');
			new YAHOO.util.Element(tr).addClass((countObject.runs.count > 0) ? "orderCountFull" : "orderCountEmpty");
			if (countObject.runs.count > 0) 
			{
				YAHOO.util.Event.addListener(tr, "click", function(e) { window.location="shipruns.html"; });
				tr.style.backgroundColor = '#DDD';
			}
			
			var td1 = document.createElement('td');
			new YAHOO.util.Element(td1).addClass("orderCountTitle");
			td1.innerHTML = 'Shipping Now:';
			var td2 = document.createElement('td');
			new YAHOO.util.Element(td2).addClass("orderCountNumber");
			td2.innerHTML = countObject.runs.count;
			if (countObject.runs.conflict > 0)
			{
				td2.style.color = '#ff0000';
			}
			
			tr.appendChild(td1);
			tr.appendChild(td2);
			
			table.appendChild(tr);
			
			
			// total orders
			var tr = document.createElement('tr');
			new YAHOO.util.Element(tr).addClass((countObject.total.count > 0) ? "orderCountFull" : "orderCountEmpty");
			if (countObject.total.count > 0) 
			{
				YAHOO.util.Event.addListener(tr, "click", function(e) { window.location="shipruns.html"; });
				tr.style.backgroundColor = '#FFF';
			}
			
			var td1 = document.createElement('td');
			new YAHOO.util.Element(td1).addClass("orderCountTitle");
			td1.innerHTML = 'Total Orders:';
			var td2 = document.createElement('td');
			new YAHOO.util.Element(td2).addClass("orderCountNumber");
			td2.innerHTML = countObject.total.count;
			
			tr.appendChild(td1);
			tr.appendChild(td2);
			
			table.appendChild(tr);
			
			el.appendChild(table);
			
			
			
			
			var el = YAHOO.util.Dom.get('flagsCountTd');
			
			var flagCells = new Array();
			for (var i in countObject.flags)
			{
				var td1 = document.createElement('td');
				var td2 = document.createElement('td');
				if (countObject.flags[i].count > 0)
				{
					td1.style.backgroundColor = countObject.flags[i].flagColour;
					//td2.style.backgroundColor = countObject.flags[i].conflict ? '#FF0000' : countObject.flags[i].flagColour;
					td2.style.backgroundColor = countObject.flags[i].flagColour;
					
					td2.style.color = (countObject.flags[i].conflict > 0) ? '#FF0000' : '';
					
					new YAHOO.util.Element(td1).addClass('orderCountFull');
					new YAHOO.util.Element(td2).addClass('orderCountFull');

					YAHOO.util.Event.addListener([td1, td2], "click", function(e, flagID) { window.location="heldorders.html?flagID=" + flagID; }, countObject.flags[i].flagID);
					
				}
				else
				{
					new YAHOO.util.Element(td1).addClass('orderCountEmpty');
					new YAHOO.util.Element(td2).addClass('orderCountEmpty');
				}
				new YAHOO.util.Element(td1).addClass('orderCountTitle');
				new YAHOO.util.Element(td2).addClass('orderCountNumber');
				
				td1.id = "flagCountTitle" + countObject.flags[i].flagID;
				td2.id = "flagCount" + countObject.flags[i].flagID;
				td1.innerHTML = countObject.flags[i].flagName + ":";
				td2.innerHTML = countObject.flags[i].count;
				flagCells.push({titleEl:td1, countEl:td2});
				
			}
			
			var rowsPerCol = 3;
			var table = document.createElement('table');
			for (var i =0; i < rowsPerCol; i++)
			{
				var tr = document.createElement('tr');
				var index = i;
				var flagCell;
				while (index < flagCells.length)
				{
					flagCell = flagCells[index];
					tr.appendChild(flagCell.titleEl);
					tr.appendChild(flagCell.countEl);
					if (index < countObject.flags.length - rowsPerCol)
					{
						tr.appendChild(document.createElement('td'));
					}
					index += rowsPerCol;
				}
				table.appendChild(tr);
			}
			
			el.appendChild(table);
			
			/*var flagsBox = YAHOO.util.Dom.get('flagsCount');
			if (!flagsBox)
			{
				flagsBox = document.createElement('span');
				flagsBox.id = 'flagsCount';
				ordersCountEl.appendChild(flagsBox);
			}
			for (var i in countObject.flags)
			{
				var flag = countObject.flags[i];
				var flagEl = YAHOO.util.Dom.get('flagCount-' + flag.flagID)
				if (!flagEl)
				{
					flagEl = document.createElement('span');
					new YAHOO.util.Element(flagEl).addClass('orderCountBox');
					new YAHOO.util.Element(flagEl).addClass('fastToolTip');
					
					flagEl.title = flag.flagName;
					flagEl.id = 'flagCount-' + flag.flagID;
					YAHOO.util.Event.addListener(flagEl, "click", function(e, flagID) { window.location="heldorders.html?flagID=" + flagID; }, flag.flagID);
					flagsBox.appendChild(flagEl);
				}
				var prevHTML = flagEl.innerHTML;
				var newHTML = flag.count > 0 ? flag.count : "&nbsp;";
				if (newHTML != prevHTML)
				{
					flagEl.style.backgroundColor = flag.count > 0 ? flag.flagColour : "transparent";
					if (animate)
					{
						toAnimate.push({el:flagEl, innerHTML:newHTML});
					}
					else
					{
						flagEl.innerHTML = newHTML;
					}
				}
				
			}
			var prevAnim;
			for (var i=toAnimate.length-1;i>=0;i--)
			{
				var obj = toAnimate[i];
				var anim = new YAHOO.util.ColorAnim(obj.el, {backgroundColor: {from: '#FFF000', to: obj.el.style.backgroundColor }}, .5, YAHOO.util.Easing.easeOut);
				if (prevAnim)
				{
					anim.onComplete.subscribe(function(e, f, prev){
						prev.anim.animate(); prev.el.innerHTML = prev.innerHTML;
					}, prevAnim);
				}
				if (i==0)
				{
					anim.animate();
					obj.el.innerHTML = obj.innerHTML;
				}
				prevAnim = {anim:anim, el:obj.el, innerHTML:obj.innerHTML};
			}*/
		}
		
		this.formatShippingInstructions = function (elCell, oRecord, oColumn, oData) {
			elCell.innerHTML = "";
			if (oRecord.getData('shippingInstructions') != '')
			{
				var img = document.createElement('img');
				img.src = '/static/images/shipping/user_comment.png';
				img.id = oRecord.getData('ID') + "-shippingInstructionsIcon";
				YAHOO.util.Dom.setStyle(img, 'float','right');
				elCell.appendChild(img);
				new YAHOO.widget.Tooltip(oRecord.getData('ID') + "-shippingInstructionsTooltip", {
						context:img.id,
						text:'<strong>Shipping Instructions:</strong><br/>' + oRecord.getData('shippingInstructions'),
						showDelay:0,
						hideDelay:0,
						preventoverlap:false
					});
			}
			elCell.innerHTML += oData;
		};
		
		this.formatCarrierValidation = function (elCell, oRecord, oColumn, oData) {
			elCell.innerHTML = "";
			if (oRecord.getData('carrierValidationErrors') && oRecord.getData('carrierValidationErrors') != '')
			{
				var img = document.createElement('img');
				img.src = '/static/images/shipping/flag_red.png';
				img.id = oRecord.getData('ID') + "-carrierValidationIcon";
				YAHOO.util.Dom.setStyle(img, 'float','right');
				elCell.appendChild(img);
				new YAHOO.widget.Tooltip(oRecord.getData('ID') + "-carrierValidationTooltip", {
						context:img.id,
						text:'<strong>Carrier Validation Failed:</strong><br/>' + oRecord.getData('carrierValidationErrors') ,
						showDelay:0,
						hideDelay:0,
						preventoverlap:false
					});
			}
			elCell.innerHTML += oData;
		};
		
		this.formatOrderItems = function (elCell, oRecord, oColumn, oData) {
			elCell.innerHTML = (oRecord.getData('orderDisplayID') + ' - ' + oRecord.getData('fullName') + '<br/>' + oRecord.getData('items'));
			ShippingAdvisor.formatShippingInstructions(elCell, oRecord, oColumn, elCell.innerHTML);
			ShippingAdvisor.formatCarrierValidation(elCell, oRecord, oColumn, elCell.innerHTML);
			
		}
		
		this.formatConflictedRows = function(dt)
		{
			YAHOO.log('Format Conflicted Rows');
			var records = dt.getRecordSet().getRecords();
			for (var i in records)
			{
				var record = records[i];
				if (record.getData('dataConflict') == 'conflict')
				{
					var el = dt.getTrEl(record);
					YAHOO.util.Dom.addClass(el, 'row-dataconflict');
				}
				else if (record.getData('dataConflict') == 'ignoreConflict')
				{
					var el = dt.getTrEl(record);
					YAHOO.util.Dom.addClass(el, 'row-dataconflictignored');
				}
				else if (record.getData('dataConflict') == 'noConflict')
				{
					var el = dt.getTrEl(record);
					YAHOO.util.Dom.removeClass(el, 'row-dataconflict')
					YAHOO.util.Dom.removeClass(el, 'row-dataconflictignored')
				}
			}
		}
		
		this.showAsEditable = function(e)
		{
			YAHOO.util.Event.preventDefault(e);
			YAHOO.util.Event.stopPropagation(e);
		
			if(this.oldBG == undefined) {
				var pos = this;
		
				while(pos && YAHOO.util.Dom.getStyle(pos, 'backgroundColor') == 'transparent') {
					pos = pos.parentNode;
				}
		
				this.oldBG = YAHOO.util.Dom.getStyle(pos, 'backgroundColor');
			}
		
			var anim = new YAHOO.util.ColorAnim (	this,	{backgroundColor:{to:'#ffffd3'}}, .5, YAHOO.util.Easing.easeOut);
			anim.animate();
		}

		this.showAsNotEditable = function(e){
			YAHOO.util.Event.preventDefault(e);
			YAHOO.util.Event.stopPropagation(e);
		
			var anim = new YAHOO.util.ColorAnim (this, {backgroundColor:{to:this.oldBG}},	.5,	YAHOO.util.Easing.easeOut);
			anim.animate();
		}
		
		this.addInlineEditor = function(target, shippingOrderID){
		
			ShippingAdvisor.inlineEditor = new YAHOO.widget.Overlay("inlineEditor", {
				context:[target.id, "tl","tl"],
				height:'30px'
			});
			ShippingAdvisor.inlineEditor.setBody('<div class="inlineEditor"><input type="text" id="' + target.id +
				'_edit" name="' + target.id +
				'" value="' +
				target.innerHTML + '"/>' + 
				'<input id="' + target.id +
				'_save" type="button" ' +
				'value="SAVE" /> OR <input id="' +
				target.id + '_cancel" type="button" ' +
				'value="CANCEL" /></div>');
		
			ShippingAdvisor.inlineEditor.render(document.body);
			ShippingAdvisor.inlineEditor.show();
		
			YAHOO.util.Event.addListener(target.id + '_save', 'click', function(){
				ShippingAdvisor.ajaxRequest('POST', 'ajax/orderDetailEdit.ajax',
				{
					success: function(o){
						target.innerHTML = YAHOO.util.Dom.get(target.id + '_edit').value;
						ShippingAdvisor.inlineEditor.hide();
						//target.style.display = 'block';
					},
					failure: function(o){
						YAHOO.util.Dom.get(target.id + '_editor').value =
						'Sorry, the update failed...';
					}
				},
				'shippingOrderID=' + shippingOrderID + "&params=" + YAHOO.lang.JSON.stringify([{target:target.id,value:escape(YAHOO.util.Dom.get(target.id + '_edit').value)}])
				);
			});
		
			YAHOO.util.Event.addListener(target.id + '_cancel', 'click', function()
			{
				ShippingAdvisor.inlineEditor.hide();
			});
		
		}
		
		// CUSTOM EVENTS
		
		this.onFlagAdd = new YAHOO.util.CustomEvent('onFlagAdd');
		this.onFlagRemove = new YAHOO.util.CustomEvent('onFlagRemove');
		this.onOrderCountUpdate = new YAHOO.util.CustomEvent('onOrderCountUpdate');
		this.onRunRemove = new YAHOO.util.CustomEvent('onRunRemove');
		this.orderInactive = new YAHOO.util.CustomEvent('orderInactive');
		this.onStepStatusChange = new YAHOO.util.CustomEvent('onStepStatusChange');
		this.onRefreshExpandedRow = new YAHOO.util.CustomEvent('onRefreshExpandedRow');
		this.onOrderRemovedFromRun = new YAHOO.util.CustomEvent('onOrderRemovedFromRun');
		this.onRowDataChange = new YAHOO.util.CustomEvent('onRowDataChange');
		
		this.fireEvents = function(events)
		{
			if (!events)
				return;
			
			for (var e in events)
			{
				var obj = events[e];
				// check that event type exists
				var event = eval("this." + obj.type);
				if (event)
				{
					event.fire(obj);
				}
			}
		}
		
		// ALERTS
		
		this.displayAlert = function (message, config)
		{
			if (!config)
			{
				config = {};
			}
			if (!config.type)
			{
				type="warning";
			}
			
			if (!config.timeout)
			{
				config.timeout = 5000;	
			}
			
			var content = '<div class="' + config.type + '"><span id="alertDismiss"><a href="#" onClick="ShippingAdvisor.hideAlert(); return false;">X</a></span>';
			
			switch(config.type)
			{
				case "warning":
					content += "<img src='/static/images/shipping/exclamation.png' align='top'/>";
			}
			content += message + "</div>";
			
			ShippingAdvisor.alertWindow = new YAHOO.widget.Overlay("alertWindow", {
				context:["breadCrumbs", "br", "br"],
				width:200,
				effect: [{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.5}]
			});
			
			ShippingAdvisor.alertWindow.setBody(content);
			
			ShippingAdvisor.alertWindow.render(document.body);
			ShippingAdvisor.alertWindow.show();
			
			/*var el = YAHOO.util.Dom.get('alertWindow');
			switch(type)
			{
			case "warning":
				el.innerHTML = "<img src='/static/images/shipping/exclamation.png' align='top'/>";
			}
			el.innerHTML += message;
			el.innerHTML += '<span id="alertDismiss"><a href="#" onClick="ShippingAdvisor.hideAlert(); return false;">X</a></span>';
			//el.style.display = 'none';
			el.style.height = 'auto';
			el.style.width = 'auto';
			var from = (el.scrollWidth + 2)*-1;
			var to = 2;
			el.style.right = from;
			//el.style.display = 'block';
			var anim = new YAHOO.util.Anim("alertWindow", {right: {from: from, to: to }}, .6, YAHOO.util.Easing.elasticOut);
			anim.animate();
			anim = new YAHOO.util.Anim("alertWindow", {opacity: {from: 0, to: 1 }}, .3, YAHOO.util.Easing.easeOut);
			anim.animate();*/
			
			if (config.timeout > 0)
			{
				setTimeout('ShippingAdvisor.hideAlert();', config.timeout);
			}
		}

		this.hideAlert = function()
		{
			ShippingAdvisor.alertWindow.hide();
			/*var el = YAHOO.util.Dom.get('alertWindow');
			var to = (el.scrollWidth + 2)*-1;
			var from = el.style.right;
			var anim = new YAHOO.util.Anim("alertWindow", {right: { to: to }}, .6, YAHOO.util.Easing.easeIn);
			anim.animate();
			anim = new YAHOO.util.Anim("alertWindow", {opacity: {from: 1, to: 0 }}, .8, YAHOO.util.Easing.easeOut);
			anim.animate();*/
		}
		
		this.showHelpText = function(config)
		{
			if (!config.width)
			{
				config.width = 350;
			}
			if (!config.height)
			{
				config.height = 'auto';
			}
			config.effect = [{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.5}];
			if (config.target)
			{
				config.context = [config.target, "tl", "tr"];
			}
			else
			{
				config.fixedcenter = true;
			}
			ShippingAdvisor.helpWindow = new YAHOO.widget.Panel("helpWindow", config);
			ShippingAdvisor.helpWindow.render(YAHOO.util.Dom.get("content"));
			var bdEl = YAHOO.util.Dom.get('helpWindow');
			ShippingAdvisor.insertHelpText({helpCode:config.helpCode, element:bdEl});
			YAHOO.util.Event.addListener(bdEl, "click", function(e){ShippingAdvisor.hideHelpText();});
			//ShippingAdvisor.helpWindow.show();
			
		}
		
		this.addHelpIcon = function(config)
		{
			$(config.parent).prepend(
				$(document.createElement('img'))
				.addClass('helpIcon')
				.attr('src', '/static/images/shipping/information.png')
				.bind('click', function(e) {
						config.target = this;
						ShippingAdvisor.showHelpText(config);
			}));
		}
		
		this.insertHelpText = function(config)
		{
			var element = YAHOO.util.Dom.get(config.element);
			element.innerHTML = '<img src="/static/images/shipping/ajax-loader.gif" />';
			var callback = {
				success:function(o){
					element.innerHTML = o.responseText.replace(/\\'/, "'");
					if(config.callback)
					{
						config.callback(config.param);
					}
				},
				failure:function(o){
					element.innerHTML = 'Help text could not be received.';
				}
			};
			ShippingAdvisor.ajaxRequest("GET", "ajax/getHelpText.ajax?id="+config.helpCode, callback);
		}
		
		this.hideHelpText = function()
		{
			ShippingAdvisor.helpWindow.hide();
		}
		
		this.yellowFade = function(object)
		{
			if (object instanceof YAHOO.widget.Tab)
			{
				var div = document.createElement('div');
				div.style.backgroundColor = '#FFF000';
				object.get('labelEl').appendChild(div, 0);
				var anim = new YAHOO.util.Anim(div, { opacity: { from: 1, to:0 } }, 1, YAHOO.util.Easing.easeOut);
				anim.onComplete.subscribe(function(o){
					object.get('labelEl').removeChild(div);
				});
				anim.animate();
			}
			else if (YAHOO.lang.isArray(object))
			{
				for (var i in object)
				{
					ShippingAdvisor.yellowFade(object[i]);
				}
			}
			else
			{
				if (object.style)
				{
					var color = object.style.backgroundColor;
					var anim = new YAHOO.util.ColorAnim(object, { backgroundColor: { from: '#FFF000', to:'#FFFFFF' } }, 1, YAHOO.util.Easing.easeOut);
					anim.animate();
				}
			}
		}
		
		this.applyToolTips = function()
		{
			var els = YAHOO.util.Dom.getElementsByClassName('fastToolTip');
			for (var i in els)
			{
				var el = els[i];
				if (!el.id)
				{
					el.id = 'auto-tooltip' + ShippingAdvisor.toolTipIndex++;
				}
				new YAHOO.widget.Tooltip("el.id"+"-tooltip",{context:el.id,showDelay:0,hideDelay:0}); 
			}
		}
		
		// FORMATTERS
		
		this.encodeEntities = function (text) {
			     encodedText = escape(text);
			     encodedText = encodedText.replace(/\//g,"%2F");
			     encodedText = encodedText.replace(/\?/g,"%3F");
			     encodedText = encodedText.replace(/=/g,"%3D");
			     encodedText = encodedText.replace(/&/g,"%26");
			     encodedText = encodedText.replace(/@/g,"%40");
			     return encodedText;
		}
		
		this.orderActionsFormatter = function(elCell, oRecord, oColumn, oData) {
			elCell.innerHTML = "";
			var div = document.createElement('div');
			new YAHOO.util.Element(div).addClass('orderActionsColumn');
			
			var actionsType = ShippingAdvisor.dataTables[ShippingAdvisor.getDataTableIndex(this)].actionsType;
			
			if (actionsType == "unshipped")
			{
					var commitIcon = document.createElement('img');
					commitIcon.src = "/static/images/shipping/lorry.png";
					YAHOO.util.Event.addListener(commitIcon, "click", function(e, shippingOrderID) { ShipRuns.commitToRuns([shippingOrderID]); }, oRecord.getData('ID'));
					commitIcon.title = 'Ship Order';
					new YAHOO.util.Element(commitIcon).addClass('activeIcon');
					div.appendChild(commitIcon);
			}
			
			if (actionsType == "shippingrun")
			{
					var removeIcon = document.createElement('img');
					removeIcon.src = "/static/images/shipping/lorry_delete.png";
					YAHOO.util.Event.addListener(removeIcon, "click", function(e, shippingOrderID) { 
						ShipRuns.removeOrdersFromRun([shippingOrderID]); 
					}, oRecord.getData('ID'));
					removeIcon.title = 'Remove From Run';
					new YAHOO.util.Element(removeIcon).addClass('activeIcon');
					div.appendChild(removeIcon);
			}
			elCell.appendChild(div);
		};
		
		this.addressFixFormatter = function(elCell, oRecord, oColumn, oData) { 
				var fullAddress = oRecord.getData('street1');
				if (oRecord.getData('street2') != '')
				{
					fullAddress += '<br />' + oRecord.getData('street2');
				} 
				fullAddress += '<br />' + oRecord.getData('cityName') + ', ' + oRecord.getData('state') + ', ' + oRecord.getData('postcode');
				var a = document.createElement('a');
				a.innerHTML = fullAddress;
				a.href ="#";
				YAHOO.util.Event.addListener(a, "click", function (e) {
					ShippingAdvisor.openAddressEditor(oRecord.getData('ID'));
				});
				elCell.innerHTML = "";
				elCell.appendChild(a);
		};
		
		this.supplierOrderFormatter = function(elCell, oRecord, oColumn, oData) {
			var ID = oRecord.getData('supplierOrderID')
			elCell.innerHTML = "<a href='printSupplierOrders.print?orders=[" + ID + "]' target='_blank'>" + ID + "</a>";
		};
		
		this.parseUnixTimestamp = function(oData) {
			if (oData != null)
			{
				return new Date(oData * 1000);
			}
			else
			{
				return null;
			}
	        }; 
		
		this.formatDate = function(el, oRecord, oColumn, oData) {
		    var oDate = oData;
		    if (oData != null)
		    {
			    if(oDate instanceof Date) {
				el.innerHTML = ShippingAdvisor.dateToString(oDate);
			    }
			    else {
				el.innerHTML = ShippingAdvisor.dateToString(ShippingAdvisor.parseUnixTimestamp(oDate));
			    }
		    }
		    else
		    {
			el.innerHTML = "";    
		    }
		};
		
		this.dateToString = function(oDate){
			if(oDate instanceof Date) {
				var now = new Date();
				if (now.getDate() == oDate.getDate() && now.getMonth() == oDate.getMonth() && now.getFullYear() == oDate.getFullYear())
					return "Today";
				else
					return oDate.getDate() + "/" +( oDate.getMonth()+1)  + "/" + oDate.getFullYear();
			}
			return 'Date Error';
		}
		
		this.dateTimeToString = function(oDate){
			if(oDate instanceof Date) {	
				return oDate.getDate() + "/" +( oDate.getMonth()+1)  + "/" + oDate.getFullYear() + " " + (oDate.getHours()+1) + ":" + (oDate.getMinutes() < 10 ? "0" : "") + (oDate.getMinutes());
			}
			return 'Date Error';
		}
		
		this.onRowSelection = function(e)
		{
			ShippingAdvisor.formatChecked(this, e.record);
		}
		
		this.onUnselectAllRows = function(e)
		{
			var records = this.getRecordSet().getRecords();
			for (var i in records)
			{
				ShippingAdvisor.formatChecked(this, records[i]);
			}
			this.updateItemCount();
		}
		
		this.checkboxSelectHandler = function(oArgs){ 
		    var elCheckbox = oArgs.target;
		    if ($(elCheckbox).parents('td').hasClass('yui-dt-col-checked'))
		    {
			    var elRecord = this.getRecord(elCheckbox);
			    if (elCheckbox.checked)
			    {
						this.onEventSelectRow(oArgs);
			    }
			    else
			    {
						this.unselectRow(elRecord);
			    }
			    this.getRecordSet().updateKey(elRecord, "checked", elCheckbox.checked);
		    }
		    this.updateItemCount();
		}
		
		// DATA TABLE FUNCTIONS
		
		// creates a datatable with builtin select functions and action buttons	
		// config is an object with the following parameters:
		// title (optional)- string to put in the H2 at the top of the data table
		// actionsType - which actions should be enabled in the actions column (matches up with the formatter)
		// initialLoad (true|false) (optional) - whether or not to load the datatable from it's source when it's created
		// container - the ID of an existing element to append the datatable to
		// divID - the ID of the outer div to be created around the datatable
		// fields - the array of fields to pass to the datasource
		// columnDefs - the array of column definitions to pass to the datatable
		// buttons - an array of objects with following parameters
		// 	label - the label to display on the button
		//	clickFn - the function which should be triggered by the button
		//	params (optional) - an object to pass to the click function
		this.createDataTable = function(config)
		{
			// set some default values
			if (!config.initialLoad)
			{
				config.initialLoad = false;
			}
			if (!config.title)
			{
				config.title = "";	
			}
			if (!config.helpText)
			{
				config.helpText = "";	
			}
			if (!config.metaFields)
			{
				config.metaFields = {};
			}
			if (!config.actionsType)
			{
				config.actionsType = "standard";	
			}
			if (!config.expandURL)
			{
				config.expandURL = 'ajax/orderDetails.ajax';
			}
			if (!config.expandKey)
			{
				config.expandKey = 'ID';
			}
			if (!config.hideSelectOptions)
			{
				config.hideSelectOptions = false;
			}
			if (!config.expandCallback)
			{
				config.expandCallback = { 
				    success : function(o) { 
				    		var args = o.argument;
					// div might not exist if user has closed the row too quickly
					if (!args.el)
					{
						return;
					}
					var shippingOrderID = args.record.getData(args.key);
					args.el.style.overflow = "hidden";
					var from = args.el.scrollHeight;
					args.el.style.height = from;
					args.el.innerHTML = o.responseText;
					
					// add buttons for any data conflict error
					var alertStackDiv = YAHOO.util.Dom.get('alertStackButtons');
					if (alertStackDiv)
					{
						var buttons = YAHOO.util.Dom.getChildren(alertStackDiv);
						new YAHOO.widget.Button(buttons[0]).addListener('click', function () {             
							ShippingAdvisor.ajaxRequest("POST", 
								"ajax/setDataConflictFlag.ajax", 
								{success:function(){}},
								"id=" + shippingOrderID + "&value=reslurpMe"
							);
						});
						
						if (buttons.length > 1)
						{
							new YAHOO.widget.Button(buttons[1]).addListener('click', function () {
								ShippingAdvisor.ajaxRequest("POST", 
									"ajax/setDataConflictFlag.ajax", 
									{
										success:function(o){
											var dt = ShippingAdvisor.getFirstDataTable(o.argument.divID);
											var record = ShippingAdvisor.dtGetRows(dt, 'ID', [o.argument.shippingOrderID])[0];
											record.setData('dataConflict', 'ignoreConflict');
											ShippingAdvisor.formatConflictedRows(dt);
											ShippingAdvisor.refreshExpandedRow();
										},
										argument:{divID:config.divID, shippingOrderID:shippingOrderID}
									},
									"id=" + shippingOrderID + "&value=ignoreConflict"
								);
							});
						}
					}
					
					// set up inline editors
					var editEls = YAHOO.util.Dom.getElementsByClassName("inlineEditable", "*", args.el);
					YAHOO.util.Event.addListener(editEls, "mouseover", ShippingAdvisor.showAsEditable);
					YAHOO.util.Event.addListener(editEls, "mouseout", ShippingAdvisor.showAsNotEditable);
					YAHOO.util.Event.addListener(editEls, "click", function (e, shippingOrderID) { 
						YAHOO.util.Event.preventDefault(e);
						YAHOO.util.Event.stopPropagation(e);
						var target = (e.srcElement) ? e.srcElement : e.target;
						ShippingAdvisor.addInlineEditor(target, shippingOrderID);
					}, shippingOrderID);
					
					var itemRows = YAHOO.util.Dom.getElementsByClassName("additionalItemInfo", "*", args.el);
					for (var item in itemRows)
					{
						var ID = itemRows[item].id.match(/\d+$/);
						var fields = YAHOO.lang.JSON.parse($("#additionalItemInfoTip-" + ID).html());
						$("#additionalItemInfoTip-" + ID).remove();
						
						var fieldNames = ['weight','length','width','height','originCountry'];
						var content = '<strong>Additional Info:</strong>';
						for (var field in fieldNames)
						{
							field = fieldNames[field];
							if (!fields[field].value)
							{
								fields[field].value = '';
							}
							content += '<br/>' + fields[field].title + ': ' + fields[field].value;
						}
						content += '<br/><strong>Click to edit</strong>';
						
						new YAHOO.widget.Tooltip("tooltip-" + ID, {
							context:itemRows[item],
							text:content,
							showDelay:0,
							hideDelay:0
						});
						$(itemRows[item]).bind("click", {fields:fields,ID:ID}, function (e) {
								ShippingAdvisor.itemInfoDialog = new YAHOO.widget.Panel("itemInfoDialog",{
									modal:true,
									width:"auto", 
									fixedcenter: true, 
									underlay:"shadow", 
									close:true, 
									visible:false
								});
								var content = '<table>';
								for (var field in fieldNames)
								{
									field = fieldNames[field];
									content += '<tr><td>' + e.data.fields[field].title + ':</td><td><input name="' + field + '-' + e.data.ID + '" value="' + e.data.fields[field].value + '"/></td><tr>';
								}
								ShippingAdvisor.itemInfoDialog.setBody(content);
								ShippingAdvisor.itemInfoDialog.render(document.body);
								$(ShippingAdvisor.itemInfoDialog.body).append($(document.createElement("input"))
									.attr({type:"button",value:"Save"})
									.bind("click", function (e) {
											var values = [];
											$(ShippingAdvisor.itemInfoDialog.body).find("input").each(function(ind, el) {
													el = $(el);
													if (el.attr("name"))
													{
														values.push({target:el.attr("name"), value:el.val()});
													}
											});
											ShippingAdvisor.ajaxRequest("POST", "ajax/orderDetailEdit.ajax", 
												{
													success:function(o){
														ShippingAdvisor.itemInfoDialog.hide();
													}
												}, 'shippingOrderID=' + shippingOrderID + '&params=' + YAHOO.lang.JSON.stringify(values));
									}));
								ShippingAdvisor.itemInfoDialog.show();
						});
					}
										
					ShippingAdvisor.updateNotesTable(shippingOrderID);
					ShippingAdvisor.updateExpandedRowSize(from);
				    }, 
				    failure : function(o) { 
							ShippingAdvisor.expandOverlay.setBody("CONNECTION FAILED!"); 
				    }
				};
			}
			
			var el = document.createElement('div');
			var content = '';
			if (config.title.length > 0)
			{
				content += config.title;
			}
			content += '<div><div id="' + config.divID + '-actions" class="grid-actions"></div>';
			if (config.helpText.length > 0)
			{
				content += '<div class="helpText">' + config.helpText + '</div>';
			}
			content += '</div>';
			content += '<div style="clear:both">';
			if (config.paginatorConfig)
			{
				if (config.paginatorConfig.containers)
				{
					config.paginatorConfig.containers.push(config.divID + '-paging');
				}
				else
				{
					config.paginatorConfig.containers = [config.divID + '-paging'];
				}
			}
			var extraPageStyle = (config.helpText.length > 0 || config.hideSelectOptions == false) ? "" : 'style="margin-top:-30px !important"';
			content += '<a id="' + config.divID + '-exportLink" class="dottedUnderline exportLink">Export Selected as CSV</a>';
			content += '<div id="' + config.divID + '-paging" class="dataTablePaging" ' + extraPageStyle + ' ></div>';
			
			if (!config.hideSelectOptions)
			{
				content += '<div class="grid-select-options"><a id="' + config.divID + '-filterLink" class="dottedUnderline">Filter...</a> <span id="' + config.divID + '-itemCount" class="grid-item-count"> <span class="grid-item-count-' + config.divID + '">0</span> items (<span id="grid-selected-count-' + config.divID + '">0</span> selected)</span>Select: <a href="#" onClick="ShippingAdvisor.dtSelectAll(\'' + config.divID + '\'); return false;\">All</a>, <a href="#" onClick="ShippingAdvisor.dtSelectNone(\'' + config.divID + '\'); return false;\">None</a></div>';
			}
			else if (config.replaceSelectText)
			{
					content += '<div class="grid-select-options">' + config.replaceSelectText + '</div>';
			}
			content += '</div>';
			content += '<div id="' + config.divID + '-filterPanel" class="dtFilterPanel" style="display:none"></div>';
			content += '<div id="' + config.divID + '"></div>';
			el.innerHTML = content;
			el.style.backgroundColor = config.colour;
			new YAHOO.util.Element(el).addClass("gridContainer");
			YAHOO.util.Dom.get(config.container).appendChild(el);
			
			// add the action buttons
			for (var i in config.buttons)
			{
				var buttonDef = config.buttons[i];
				if (!buttonDef.className)
				{
					buttonDef.className = "actionButton";	
				}
				
				if (!buttonDef.params)
				{
					buttonDef.params = {divID:config.divID};
				}
				else
				{
					buttonDef.params.divID = config.divID;
				}
				
				var buttonID = (buttonDef.code ? buttonDef.code : buttonDef.className) + '-' + (config.tableID ? config.tableID : config.divID);
				$(document.createElement('div'))
				.css("float", "left")
				.attr("id", buttonID+'Span')
				.append($(document.createElement('button'))
				.html(buttonDef.label)
				.addClass(buttonDef.className)
				.addClass("gridButton")
				.attr("id", buttonID)
				.bind("click", {clickFn:buttonDef.clickFn, params:buttonDef.params}, function (e) {
					ShippingAdvisor.actionButtonHandler(e, e.data);
				}))
				.appendTo('#' + config.divID + '-actions');
				
				eval('var functionExists = ShippingAdvisor.' + buttonDef.code + 'Callback;');
				
				
				if (functionExists)
				{
					functionExists(YAHOO.lang.merge(config, {buttonID:buttonID, buttonDef:buttonDef}));
				}
			}
			
			/* make sure fields contains the dataconflict field */
			config.fields.push("dataConflict");

			var ds = new YAHOO.util.DataSource(config.dataSrc);
			ds.responseType = YAHOO.util.DataSource.TYPE_JSON;
			ds.connXhrMode = "queueRequests";
			ds.connMethodPost = true; 
			ds.responseSchema = {
			    resultsList: "rows",
			    fields: config.fields,
			    metaFields:config.metaFields
			};
			
			var dtConfig = {initialLoad:config.initialLoad, width:'auto'};
			if (config.extraConfig)
			{
				dtConfig = YAHOO.lang.merge(dtConfig, config.extraConfig);
			}
			if (config.paginatorConfig)
			{
				dtConfig = YAHOO.lang.merge(dtConfig, {paginator:new YAHOO.widget.Paginator(config.paginatorConfig)});
			}
					
			var dt = new YAHOO.ShippingAdvisor.ext.DataView(config.divID, config.columnDefs, ds, dtConfig);
			dt.initiated = false;
			dt.showTableMessage("Loading data...");
			ShippingAdvisor.dataTables.push({dt:dt, divID: config.container, actionsType:config.actionsType, expandURL:config.expandURL, expandCallback:config.expandCallback, expandKey:config.expandKey});
			
			// only apply checkboxClickEvent if there is a checked column defined
			for (var i in config.columnDefs)
			{
				if (config.columnDefs[i].key == 'checked')
				{
					dt.subscribe("checkboxClickEvent", ShippingAdvisor.checkboxSelectHandler);
					break;
				}
			}
			
			dt.handleDataReturnPayload = function(request, response, payload){
				if (payload)
				{
					payload.totalRecords = response.results.length;
				}
				else
				{
					payload = {totalRecords: response.results.length};
				}
				return payload;
			} 
			
			// get rid of any expanded rows before sorting because they mess it up
			dt.subscribe("headerLabelMousedownEvent", function (e) {
				ShippingAdvisor.reduceAllRows()
			});
			
			//dt.subscribe("rowMouseoverEvent", dt.onEventHighlightRow);
			//dt.subscribe("rowMouseoutEvent", dt.onEventUnhighlightRow);
			dt.subscribe("rowSelectEvent", ShippingAdvisor.onRowSelection);
			dt.subscribe("rowUnselectEvent", ShippingAdvisor.onRowSelection);
			
			dt.subscribe("initEvent", dt.updateItemCount);
			dt.subscribe("initEvent", function(e) { 
				YAHOO.log('Init Event');
				ShippingAdvisor.formatConflictedRows(this); 
				this.initiated = true;
			});
			dt.subscribe("dataReturnEvent", function(e) {
				ShippingAdvisor.reduceAllRows();
			});
			dt.subscribe("rowAddEvent", dt.updateItemCount);
			dt.subscribe("rowAddEvent", function(e) { 
				if (this.initiated)
				{
					YAHOO.log('Row Add');
				}
				ShippingAdvisor.formatConflictedRows(this); 
			});

			dt.subscribe("rowsAddEvent", dt.updateItemCount);
			dt.subscribe("rowsAddEvent", function(e) { ShippingAdvisor.formatConflictedRows(this); });
			dt.subscribe("sortedByChange", function(e) { ShippingAdvisor.formatConflictedRows(this); });
			
			YAHOO.util.Event.addListener(config.divID + '-filterLink', "click", function (e, dt) {
				dt.showFilterPanel();
			}, dt);
			
			YAHOO.util.Event.addListener(config.divID + '-exportLink', "click", function (e, dt) {
				dt.exportCSV();
			}, dt);
			
			dt.getRecordSet().subscribe("resetEvent", function(e, dt) {
				// reset all selections as we store it against the record
				dt._unselectAllTrEls();
				dt._unselectAllTdEls();
				dt._aSelections = [ ];
			}, dt);
			
			
			var recordAddHandler = function(e, dt) {
				var records = e.records;
				for (var i in records)
				{
						if (records[i].getData('checked') == true)
						{
								ShippingAdvisor.selectRow(dt, records[i]);
						}
				}
			}
			dt.getRecordSet().subscribe("recordAddEvent", recordAddHandler, dt);
			dt.getRecordSet().subscribe("recordsAddEvent", recordAddHandler, dt);
			
			if (dt.get('paginator'))
			{
				var pag = dt.get('paginator');
				if (pag instanceof YAHOO.widget.Paginator)
				{
					pag.subscribe('changeRequest', function(e, dt) {
						YAHOO.log('Page Change');
						ShippingAdvisor.formatConflictedRows(dt); 
						ShippingAdvisor.reduceAllRows();
					}, dt);
				}
			}
			
			dt.originalConfig = config;
			
			return dt;
				
		}
		
		// handles all clicks to action buttons on datatables
		this.actionButtonHandler = function(e, config)
		{
			config.clickFn(config.params);
		}
				
		this.subtractArray = function(a1,a2)
		{
			if (!a2 || a2.length == 0)
			{
				return a1;
			}
			for (var i=a1.length;i>=0;i--)
			{ 
				 for (var j=0; j<a2.length;j++)
				 { 
					 
					 if (a1[i]==a2[j]) 
					 { 
						a1.splice(i,1);
					 }
				 } 
			} 
			return a1;
		}
		
		this.getParentDataTable = function(record)
		{
			for (var i in ShippingAdvisor.dataTables)
			{
				if (ShippingAdvisor.dataTables[i].dt.getRecordIndex(record) != null)
				{
					return ShippingAdvisor.dataTables[i].dt;	
				}
			}
		}
		
		this.getDataTableIndex = function(dt)
		{
			for (var i = 0;i<ShippingAdvisor.dataTables.length;i++)
			{
				if (ShippingAdvisor.dataTables[i].dt == dt)
				{
					return i;
				}
			}
		}
		
		this.getRecordValues = function(dt, key, selected)
		{
			var values = new Array();
			var records = selected ? ShippingAdvisor.dtGetSelectedRecords(dt) : dt.getRecordSet.getRecords();
			for (var i in records)
			{
				values.push(records[i].getData(key));
			}
			return values;
		}
		
		
		this.refreshDataTables = function(tables)
		{
			ShippingAdvisor.reduceAllRows();
			for (var i in tables)
			{
				
				var dt = YAHOO.lang.isString(tables[i]) ? ShippingAdvisor.getFirstDataTable(tables[i]) : tables[i];
				dt.getDataSource().sendRequest("", dt.onDataReturnInitializeTable, dt);
			}
		}
		
		this.refreshAllDataTables = function()
		{
			var tables = new Array();
			for (var i in ShippingAdvisor.dataTables)
			{
				tables.push(ShippingAdvisor.dataTables[i].dt);
			}
			ShippingAdvisor.refreshDataTables(tables);
		}
		
		this.getFirstDataTable = function(divID)
		{
			var tables = ShippingAdvisor.getDataTableChildren(divID);
			if (tables.length > 0)
			{
				return tables[0];
			}
			else
			{
				return null;	
			}
		}
		
		this.selectRow = function(dt, record)
		{
			dt.selectRow(record);
			ShippingAdvisor.formatChecked(dt, record)
		}
		
		this.unselectRow = function(dt, record)
		{
			dt.unselectRow(record);
			ShippingAdvisor.formatChecked(dt, record)
		}
		
		this.formatChecked = function(dt, record)
		{
			var column = dt.getColumn('checked');
			if (column)
			{
				record.setData('checked', dt.isSelected(record));
				if (dt.getTrIndex(record) !== null)
				{
					dt.formatCell(dt.getTdLinerEl({record:record, column:column}));
				}
				
			}
		}
		
		this.getDataTableChildren = function(divID)
		{
			if (YAHOO.lang.isString(divID))
			{
				divID = "#"+divID;
			}
			var ret = new Array();
			$(divID).find("thead>tr.yui-dt-first").each(function ()
			{
				for (var i in ShippingAdvisor.dataTables)
				{
					if ($(this).find("th:first").attr('id').indexOf(ShippingAdvisor.dataTables[i].dt.getId()) != -1)
					{
						ret.push(ShippingAdvisor.dataTables[i].dt);
					}
				}
			});
			return ret;
		}
		
		//pass in the root node to search under and the field to return
		this.getSelectedOrders = function(divID, field)
		{
			var shippingOrderIDs = new Array();
			var tables = ShippingAdvisor.getDataTableChildren(divID);
			for (var t in tables)
			{
				var dt = tables[t];
				var selected = dt.getSelectedRows();
				for (var j = 0; j < selected.length; j++)
				{
					var rec = dt.getRecord(selected[j]).getData();
					shippingOrderIDs.push(rec[field]);
				}
			}
			return shippingOrderIDs;
		}
		
		this.removeSelectedRows = function(divID)
		{
			var tables = ShippingAdvisor.getDataTableChildren(divID);
			for (var t in tables)
			{
				var removeRecords = new Array();
				var dt = tables[t];
				var selected = dt.getSelectedRows();
				for (var j = 0; j < selected.length; j++)
				{
					removeRecords.push(dt.getRecord(selected[j]));
				}
				ShippingAdvisor.dtRemoveRowsAnimate(dt, removeRecords);
			}
		}
		
		// parameters expected:
		// divID - root DIV of table (or DataTable)
		// shippingOrderIDs - values to match
		// key (optional) - key to match against
		// colour (optional) - colour to fade into when rows are removed
		this.dtRemoveRows = function(params)
		{
			
			ShippingAdvisor.reduceAllRows();
			if (!params.key)
			{
				params.key = "ID";
			}
			var tables = ShippingAdvisor.getDataTableChildren(params.divID);
			for (var t in tables)
			{
				var dt = tables[t];
				var removeRecords = new Array();
				var records = dt.getRecordSet().getRecords();
				for (var i = 0; i < params.shippingOrderIDs.length; i++)
				{
					for (var j = 0; j < records.length; j++)
					{
						var rec = records[j];
						var recID = rec.getData(params.key);
						if (recID == params.shippingOrderIDs[i])
						{
							removeRecords.push(rec);
							break;
						}
					}
				}
				ShippingAdvisor.dtRemoveRowsAnimate(dt, removeRecords, params.colour);
			}
		}
		
		this.dtRemoveRowsAnimate = function(dt, records, colour)
		{
			if (!colour)
			{
				colour = "#FFF000";
			}
			var visibleEls = new Array();
			var visibleRecs = new Array();
			for (var i = records.length; i>=0;i--)
			{
				if (dt.getTrIndex(records[i]) !== null)
				{
					visibleEls.push(dt.getTrEl(records[i]));
					visibleRecs.push(records[i]);	
				}
				dt.unselectRow(records[i]);
			}
			var finalRecords = ShippingAdvisor.subtractArray(dt.getRecordSet().getRecords(),records);
			var finalData = new Array();
			for (var i in finalRecords)
			{
				finalData.push(finalRecords[i].getData());
			}
			dt.getRecordSet().replaceRecords(finalData);
			
			var anim = new YAHOO.util.ColorAnim(visibleEls, { backgroundColor: { from: '#FFFFFF', to: colour } }, .5, YAHOO.util.Easing.easeIn);
			anim.onComplete.subscribe(function(e, f, params) {
				for (var j in params.els)
				{
					params.els[j].style.backgroundColor = '';
				}
				/*for (var j in params.records)
				{
					params.dt.deleteRow(params.records[j]);
				}*/
				var pag = dt.get('paginator');
				if (pag instanceof YAHOO.widget.Paginator)
				{
					pag.setTotalRecords(finalRecords.length);
				}
				dt.render();
				dt.updateItemCount();
				ShippingAdvisor.formatConflictedRows(dt);
				
			}, {dt:dt, records:visibleRecs, els:visibleEls});
			anim.animate();
		}
		
		this.dtGetSelectedRecords = function(dt)
		{
			if (YAHOO.lang.isString(dt))
			{
				// we have a divID instead of a datatable
				dt = ShippingAdvisor.getFirstDataTable(dt);
			}
			var recordIDs = dt.getSelectedRows();
			var records = new Array();
			for (var i in recordIDs)
			{
				records.push(dt.getRecord(recordIDs[i]));
			}
			return records;
		}
		
		this.dtGetRows = function(divID, key, values)
		{
			var found = new Array();
			var tables;
			if (divID instanceof YAHOO.widget.DataTable)
			{
				tables = [divID];
			}
			else
			{
				tables = ShippingAdvisor.getDataTableChildren(divID);
			}
			for (var t in tables)
			{
				var dt = tables[t];
				var records = dt.getRecordSet().getRecords();
				for (var j = 0; j < records.length; j++)
				{
					var rec = records[j];
					var recID = rec.getData(key);
					for (var k in values)
					{
						if (recID == values[k])
						{
							found.push(rec);
						}
					}
					
				}
			}
			return found;
		}
		
		this.dtSelectAll = function(divID)
		{
			var tables = ShippingAdvisor.getDataTableChildren(divID);
			for (var t in tables)
			{
				var dt = tables[t];
				dt.selectAllRows();
			}
		}
		
		this.dtSelectNone  = function(divID)
		{
			var tables = ShippingAdvisor.getDataTableChildren(divID);
			for (var t in tables)
			{
				var dt = tables[t];
				dt.unselectAllRows();
			}
		}
		
		this.dtSelectByField = function(divID, field, values)
		{
			var tables = ShippingAdvisor.getDataTableChildren(divID);
			for (var t in tables)
			{
				var dt = tables[t];
				var record;
				var length = dt.getRecordSet().getLength();
				for (var i = 0;i < length;i++) 
				{
					record = dt.getRecord(i);
					for (var j in values)
					{
						
						if (record.getData(field) == values[j])
						{
							ShippingAdvisor.selectRow(dt, record);
						}
						else
						{
							ShippingAdvisor.unselectRow(dt, record);
						}
					}
				}
			}
		}
		
		this.expandFormatter = function(elCell, oRecord, oColumn, oData) { 
		
			var rowID = YAHOO.util.Dom.getAncestorByTagName(elCell, 'tr').id;
			var shippingOrderID = oRecord.getData()['ID'];
			
			elCell.innerHTML = "";
			
			var openDiv = document.createElement('div');
			elCell.appendChild(openDiv);
			openDiv = new YAHOO.util.Element(openDiv);
			openDiv.addClass('expand-col-closed');
			
			var closeDiv = document.createElement('div');
			elCell.appendChild(closeDiv);
			closeDiv.style.display = 'none';
			closeDiv = new YAHOO.util.Element(closeDiv);
			closeDiv.addClass('expand-col-open');
			
			var dtMeta = ShippingAdvisor.dataTables[ShippingAdvisor.getDataTableIndex(this)];
				
			openDiv.addListener("click", function(e, params) {
				ShippingAdvisor.expandRow({value:params.shippingOrderID, url:params.url, dataTables:[params.dt], callback:params.callback});
			}, {dt:this, shippingOrderID:shippingOrderID, callback:dtMeta.expandCallback, url:dtMeta.expandURL});
			
			closeDiv.addListener("click", function(e, params) {
				ShippingAdvisor.reduceRow({cell:params.cell, dataTables:[params.dt]});
			}, {cell:elCell, dt:this});
				
		};
		
		/**
		 * Expand a row based on a key/value pair
		 * @param {Object} params	An object with the following members:
		 				 - key : the key within the datasource to match on
						 - value : the value within the datasource to match on
						 - dataTables : an array of datatables to search within
						 - url : the url to call to receive the raw html to place into the expanded row
						 - callback : the callback object to pass to the ajax request
		*/
		
		this.expandRow = function(params)
		{
			if (!params.key)
			{
				params.key = 'ID';
			}
			if (!params.dataTables)
			{
				params.dataTables = ShippingAdvisor.getDataTableChildren('content');
			}
			
			
			for (var i in params.dataTables)
			{
				var dt = params.dataTables[i];
				var callback = params.callback ? params.callback : ShippingAdvisor.dataTables[ShippingAdvisor.getDataTableIndex(dt)].expandCallback;
				var url = params.url ? params.url : ShippingAdvisor.dataTables[ShippingAdvisor.getDataTableIndex(dt)].expandURL;
				var expandKey = ShippingAdvisor.dataTables[ShippingAdvisor.getDataTableIndex(dt)].expandKey;
				var records = dt.getRecordSet().getRecords();
				for (var j in records)
				{
					if (records[j].getData(params.key) == params.value)
					{
						ShippingAdvisor.reduceAllRows();
						
						// change expander widget
					 // try to find a column with the key 'expander'
					 var column = dt.getColumn('expander');

					 // otherwise assume it's the last column
					 if (!column)
					 {
					 	column = dt.getColumn(dt.getColumnSet().getDefinitions().length-1);
					 }
					 
					
					 var expanderEl = dt.getTdLinerEl({record:records[j], column:column});
					  ShippingAdvisor.expandedRecord = {record:records[j], dt:ShippingAdvisor.dataTables[ShippingAdvisor.getDataTableIndex(dt)], cell:expanderEl};
					 new YAHOO.util.Element(expanderEl).addClass('row-expanded');
					 var children = YAHOO.util.Dom.getChildren(expanderEl);
					 children[0].style.display = 'none';
					 children[1].style.display = '';
									
						// expand this row
						var rowTrEl = dt.getTrEl(records[j]);
						
						if (ShippingAdvisor.expandOverlay && ShippingAdvisor.expandOverlay.cfg)
						{
							ShippingAdvisor.expandOverlay.destroy();
						}
						
						ShippingAdvisor.expandOverlay = new YAHOO.widget.Overlay("expandOverlay", {
							context:[expanderEl, "tr", "br"]
						});
						
						ShippingAdvisor.expandOverlay.setBody('<div class="expandOverlayWrapper"><table><tr><td rowspan="2" class="shadow"><div id="expandDiv" class="rem-data-expand" style="height:0px"><img src="/static/images/shipping/ajax-loader.gif" /> Loading Data...</div></td><td height="10px" style="text-align:right; width:10px" class="shadow"><img src="/static/images/shipping/shadow-top-right.png"/></td></tr><tr><td class="shadow expandRightShadow">&nbsp;</td></tr></table></div><div class="expandBottomRightShadow"><img src="/static/images/shipping/shadow-bottom-left.png" style="float:left"/><div class="expandBottomShadow"></div></div>');
						ShippingAdvisor.expandOverlay.render(dt.getContainerEl());
						ShippingAdvisor.expandOverlay.show();
						
						var div =	YAHOO.util.Dom.get('expandDiv');
						var to = div.scrollHeight;
						var anim = new YAHOO.util.Anim(div, { height: { from: 0, to: to } }, .5, YAHOO.util.Easing.easeOut);
						anim.animate();
						
						callback.argument = {el:div, key:params.key, record:records[j], dt:dt};
						
						ShippingAdvisor.ajaxRequest("GET", url+"?"+expandKey+"="+records[j].getData(expandKey), callback);
						
						return;
					}
				}
			}
			
		}
		
		this.refreshExpandedRow = function ()
		{
			if (ShippingAdvisor.expandedRecord && ShippingAdvisor.expandedRecord.record)
			{
				var callback = ShippingAdvisor.expandedRecord.dt.expandCallback;
				callback.argument = {el:YAHOO.util.Dom.get('expandDiv'), key:ShippingAdvisor.expandedRecord.dt.expandKey, record:ShippingAdvisor.expandedRecord.record, dt:ShippingAdvisor.expandedRecord.dt};
				var url = ShippingAdvisor.expandedRecord.dt.expandURL;
				var expandKey = ShippingAdvisor.expandedRecord.dt.expandKey;
				ShippingAdvisor.ajaxRequest("POST", url+"?"+expandKey+"="+ShippingAdvisor.expandedRecord.record.getData(expandKey), callback);
				return;
			}
		}
		
		this.updateExpandedRowSize = function ()
		{
				var div = YAHOO.util.Dom.get('expandDiv');
				var to = div.scrollHeight;
				var anim = new YAHOO.util.Anim(div, { height: { to: to } }, .35, YAHOO.util.Easing.easeOut);
				anim.animate();	
		}
		
		// helper function to return values of all checkboxes that are not checked
		this.getUncheckedCheckboxValues = function (form)
		{
			var inputs = YAHOO.util.Dom.get(form).getElementsByTagName('input');
			var values = new Array();
			for (var i =0; i<inputs.length;i++)
			{
				if ((inputs[i].getAttribute("type") == "checkbox"))
				{
					values.push(inputs[i].getAttribute("name") + "=" + inputs[i].value);
				}
				
			}
			return values.join("&");
		}
		
		/**
		 * Reduce a row based on a key/value pair
		 * @param {Object} params	An object with the following members:
		 				 - cell : the liner cell for the expand column, if present uses this to determine row
		 				 - key : the key within the datasource to match on
						 - value : the value within the datasource to match on
						 - dataTables : an array of datatables to search within
						 - url : the url to call to receive the raw html to place into the expanded row
						 - callback : the callback object to pass to the ajax request
						 
		*/
		this.reduceRow = function(params)
		{
			if (!params.key)
			{
				params.key = 'ID';
			}
			if (!params.dataTables)
			{
				params.dataTables = ShippingAdvisor.getDataTableChildren('content');
			}
			for (var i in params.dataTables)
			{
				var dt = params.dataTables[i];
				var record;
				if (params.cell)
				{
					record = dt.getRecord(params.cell);
				}
				else
				{
					for (var j in records)
					{
						if (records[j].getData(params.key) == params.value)
						{
							record = records[j];
						}
					}
				}
				if (record)
				{
					if (!params.cell)
					{
						var column = dt.getColumn('expander');
						
						// otherwise assume it's the last column
						if (!column)
						{
							column = dt.getColumn(dt.getColumnSet().getDefinitions().length-1);
						}
						params.cell = dt.getTdLinerEl({record:record, column:column});
					}
					new YAHOO.util.Element(params.cell).removeClass('row-expanded');
					var children = YAHOO.util.Dom.getChildren(params.cell);
					
					children[1].style.display = 'none';
					children[0].style.display = '';
					
					if (ShippingAdvisor.expandOverlay && ShippingAdvisor.expandOverlay.cfg)
					{
						ShippingAdvisor.expandOverlay.destroy();
					}
					
				}
				
			}
			if (ShippingAdvisor.inlineEditor && ShippingAdvisor.inlineEditor.cfg)
			{
				ShippingAdvisor.inlineEditor.destroy();
			}
			
		}
		
		this.reduceAllRows = function()
		{
			if (ShippingAdvisor.expandedRecord)
			{
				ShippingAdvisor.reduceRow({cell:ShippingAdvisor.expandedRecord.cell, dataTables:[ShippingAdvisor.expandedRecord.dt.dt]});
			}
			if (ShippingAdvisor.expandOverlay && ShippingAdvisor.expandOverlay.cfg)
			{
				ShippingAdvisor.expandOverlay.destroy();
			}
			if (ShippingAdvisor.inlineEditor && ShippingAdvisor.inlineEditor.cfg)
			{
				ShippingAdvisor.inlineEditor.destroy();
			}
		}
		
		this.attachMinusButtons = function(startPoint)
		{
			var minusButtons = YAHOO.util.Dom.getElementsByClassName("minus-button", "input", startPoint);
			for (var index in minusButtons)
			{
				new YAHOO.widget.Button(minusButtons[index], {label:"-"});
			}
		}
		
		// NOTES FUNCTIONS
		
		this.updateNotesTable = function(shippingOrderID, showSystem)
		{
			$("#notesDetail").html('<table class="infotable"><tbody><tr><td><img src="/static/images/shipping/ajax-loader.gif"/> Loading...</td></tr></tbody></table>');
			if (!showSystem)
			{
				showSystem = 0;
			}
			ShippingAdvisor.showSystemNotes = showSystem;
			var callback =  {
				success:function(o) {
					
					var obj = YAHOO.lang.JSON.parse(o.responseText);
					var tbody = YAHOO.util.Selector.query("tbody", "notesDetail", true);
					// if the row has been closed tbody will not exist
					if (!tbody)
					{
						return;
					}
					//remove all TR elements from notes table
					var existingRows = YAHOO.util.Dom.getChildren(tbody);
					// except first row as it is the header
					for (var i in existingRows)
					{
						tbody.removeChild(existingRows[i]);
					}
					if (obj.rows.length == 0)
					{
						// add blank tr
						var tr = document.createElement('tr');
						var td = document.createElement('td');
						td.setAttribute('colspan', '3');
						td.innerHTML = '<div>No Notes</div>';
						td = new YAHOO.util.Element(td);
						
						td.addClass('noteEmpty');
						tr.appendChild(td.get('element'));
						tbody.appendChild(tr);
					}
					for (var row in obj.rows)
					{
						var tr = document.createElement('tr');
						// date
						td = document.createElement('th');
						td.innerHTML = "<div>" + ShippingAdvisor.dateTimeToString(ShippingAdvisor.parseUnixTimestamp(obj.rows[row].noteDate)) + "</div>";
						new YAHOO.util.Element(td).addClass('noteValue');
						tr.appendChild(td);
						// username
						var td = document.createElement('th');
						td.innerHTML = '<div style="text-align:right">' + (obj.rows[row].shortName ? obj.rows[row].shortName : obj.rows[row].username) + "</div>";
						new YAHOO.util.Element(td).addClass('noteValue');
						tr.appendChild(td);
						
						tbody.appendChild(tr);
						// text
						var tr = document.createElement('tr');
						td = document.createElement('td');
						td.colSpan = 2;
						td.innerHTML = "<div>" + obj.rows[row].noteText.replace(/\n/g, "<br />") + "</div>";
						new YAHOO.util.Element(td).addClass('noteValue');
						tr.appendChild(td);
						
						tbody.appendChild(tr);
						
					}
					ShippingAdvisor.updateExpandedRowSize();
					
				},
				failure:function(o){
					
				}
			};
			if (YAHOO.util.Dom.get('notesDetail'))
			{
				ShippingAdvisor.ajaxRequest("GET", "ajax/orderNotes.ajax?shippingOrderID=" + shippingOrderID + "&showSystem=" + showSystem, callback);
			}
			
		}
		
		
		this.toggleChecked = function(check)
		{
			var table = YAHOO.util.Dom.getAncestorByClassName(check, "yui-dt-table");
			var ind = table.id.replace(/yui-dt(\d+).*/, "$1");
			var dt = ShippingAdvisor.dataTables[ind].dt;
			var record;
			var length = dt.getRecordSet().getLength();
			for (var i = 0;i < length;i++) 
			{
				if (check.checked)
				{
					record = dt.getRecord(i);
					dt.selectRow(record);
					record = record.getData();
					record['checked'] = true;
					dt.updateRow(i, record);
				}
				else
				{
					record = dt.getRecord(i);
					dt.unselectRow(record);
					record = record.getData();
					record['checked'] = false;
					dt.updateRow(i, record);	
				}
			}
		}
		
		// TABVIEW FUNCTIONS
		
		this.addMainTab = function(tab, open)
		{
			YAHOO.util.Dispatcher.delegate(tab, ShippingAdvisor.mainTabView);
			if (open)
			{
				ShippingAdvisor.activeTab = {index:ShippingAdvisor.mainTabView.getTabIndex(tab), tab:tab};	
			}
		}
		
		this.switchTab = function(tabIndex) {
			ShippingAdvisor.mainTabView.set('activeTab', ShippingAdvisor.mainTabView.getTab(tabIndex));
		};
		
		this.tabCallback = function(e)
		{
			ShippingAdvisor.activeTab = {index:ShippingAdvisor.mainTabView.getTabIndex(e.newValue), tab:e.newValue};
			return true;
		}
		
		this.removeItemsFromBackOrder = function(items)
		{
			var callback = {
				success:function(o) {
					// refresh the currently expanded row
					ShippingAdvisor.refreshExpandedRow();
				}
			};
			ShippingAdvisor.ajaxRequest("POST", "ajax/removeItemFromBackOrder.ajax?items="+YAHOO.lang.JSON.stringify(items), callback);
		}
		
		// DIALOGS
		
		this.openNoteEditor = function(shippingOrderID)
		{
			ShippingAdvisor.inlineEditor = new YAHOO.widget.Overlay("inlineEditor", 
				{
					width:"320px", 
					constraintoviewport: true, 
					underlay:"shadow", 
					context:["notesHeader", "tr", "tr"],
					visible:false
				}
			);
			ShippingAdvisor.inlineEditor.setBody("<div class='inlineEditor'>Add Note to Order<br/><textarea cols='30' rows='3' id='noteText'></textarea><div><input type='button' id='noteSaveButton' value='Save' /><input type='button' id='noteCancelButton' value='Cancel' /></div></div>");
			ShippingAdvisor.inlineEditor.render(document.body);
			new YAHOO.widget.Button("noteCancelButton").addListener('click', function() {ShippingAdvisor.inlineEditor.hide();});
			new YAHOO.widget.Button("noteSaveButton").addListener('click', function() {
					var saveCallback = {
						success: function () {
							ShippingAdvisor.updateNotesTable(shippingOrderID);
							ShippingAdvisor.inlineEditor.hide();
						},
						failure:function(o){
							ShippingAdvisor.inlineEditor.hide();
						}
					}
					var postData = "shippingOrderID="+ shippingOrderID;
					postData += "&noteText=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('noteText').value);
					ShippingAdvisor.ajaxRequest("POST", "ajax/addNote.ajax", saveCallback, postData);
				}
			);
			ShippingAdvisor.inlineEditor.show();
			
		}
		
		this.openAddressEditor = function(shippingOrderID)
		{
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("addressEdit", 
				{
					width:"auto", 
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true
				}
			);
			ShippingAdvisor.actionPanel.setHeader("Edit Address");
			ShippingAdvisor.actionPanel.setBody("Loading...");
			
			var callback = {
				success: function (o) {
					ShippingAdvisor.actionPanel.setBody(o.responseText);
					new YAHOO.widget.Button("addressCancelButton").addListener('click', function() {ShippingAdvisor.actionPanel.hide();});
					new YAHOO.widget.Button("addressSaveButton").addListener('click', function() 
						{
							var saveCallback = {
								success: function (o) {
									var obj = YAHOO.lang.JSON.parse(o.responseText);
									if (obj.status == 'success')
									{
										ShippingAdvisor.actionPanel.hide();
										ShippingAdvisor.refreshExpandedRow();
									}
									else if (obj.status == 'addrerror')
									{
										var suggestions = YAHOO.util.Dom.get('addressSuggestions');
										
										suggestions.innerHTML = '';
										for (var i in obj.suggestions)
										{
											suggestions.innerHTML += '<option>' + obj.suggestions[i] + '</option>';
										}
										YAHOO.util.Dom.get('addressSuggestionsTd').style.display = '';
										
										YAHOO.util.Dom.get('addressErrorDisplay').innerHTML = 'Address did not validate, try using the suggestions on the right.';
									}
								},
								failure:function(o){
									ShippingAdvisor.actionPanel.hide();
								}
							}
							var postData = "shippingOrderID="+ shippingOrderID;
								postData += "&companyName=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeCompanyName').value);
							postData += "&firstName=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeFirstName').value);
							postData += "&lastName=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeLastName').value);
							postData += "&street1=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeStreet1').value);
							postData += "&street2=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeStreet2').value);
							postData += "&cityName=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeCity').value);
							postData += "&state=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeState').value);
							postData += "&postcode=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangePostcode').value);
							postData += "&countryCode=" +  ShippingAdvisor.encodeEntities(YAHOO.util.Dom.get('addressChangeCountryCode').value);
							ShippingAdvisor.ajaxRequest("POST", "ajax/editAddress.ajax?shippingOrderID=" + shippingOrderID, saveCallback, postData);
						}
					);

					YAHOO.util.Event.addListener('addressSuggestions','change', function (e) {
						var split = e.target.options[e.target.selectedIndex].innerHTML.split(",");
						if (split[1])
						{
							var cityEl = YAHOO.util.Dom.get('addressChangeCity');
							var stateEl = YAHOO.util.Dom.get('addressChangeState');
							var postcodeEl = YAHOO.util.Dom.get('addressChangePostcode');
							var animList = new Array();
							if (cityEl.value != split[0])
							{
								animList.push(cityEl);
							}
							if (stateEl.value != split[1])
							{
								animList.push(stateEl);
							}
							if (postcodeEl.value != split[2])
							{
								animList.push(postcodeEl);
							}
							cityEl.value = split[0];
							stateEl.value = split[1];
							postcodeEl.value = split[2];
							var bg = cityEl.style.backgroundColor;
							var anim = new YAHOO.util.ColorAnim(animList, { backgroundColor: { from: '#FFF000', to: '#FFFFFF' } }, 1, YAHOO.util.Easing.easeOut);
							anim.animate();
						}
					});
				},
				failure:function(o){
					ShippingAdvisor.actionPanel.hide();
				}
			};
			
			ShippingAdvisor.ajaxRequest("POST", "ajax/addressEditDialog.ajax?shippingOrderID=" + shippingOrderID, callback);
			ShippingAdvisor.actionPanel.render(document.body);
			ShippingAdvisor.actionPanel.show();
		};
		
		this.openCarrierDialog = function(shippingOrderIDs)
		{
			
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("changeCarrier", 
				{
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true
				}
			);
			if (shippingOrderIDs.length > 1)
			{
				ShippingAdvisor.actionPanel.setHeader("Change Carrier for " + shippingOrderIDs.length + " Orders");	
			}
			else
			{
				ShippingAdvisor.actionPanel.setHeader("Change Carrier");
			}
			
			ShippingAdvisor.actionPanel.setBody('<div id="changeCarrierBody">Loading...</div>');
			
			var callback = {
				success: function (o) {
					var obj = YAHOO.lang.JSON.parse(o.responseText);
					var bd = YAHOO.util.Dom.get('changeCarrierBody');
					bd.innerHTML = "";
					
					var shipBySelect = document.createElement('select');
					for (var i in obj.shipBys)
					{
						shipBySelect.innerHTML += '<option value="' + obj.shipBys[i].shipByID + '">' + obj.shipBys[i].description + ' - ' + obj.shipBys[i].carrierName + '</option>';
					}
					
					bd.appendChild(shipBySelect);
					
					var serviceSelect = document.createElement('select');
					obj.select = serviceSelect;
					bd.appendChild(serviceSelect);
					
					var populateService = function(e, obj, value)
					{
						obj.select.innerHTML = "";
						var carrierID;
						if (e)
						{
							value = e.target.options[e.target.selectedIndex].value;
						}
						for (var i in obj.shipBys)
						{
							if (obj.shipBys[i].shipByID == value)
							{
								carrierID = obj.shipBys[i].carrierID;
							}
						}
						for (var i in obj.services)
						{
							if (obj.services[i].carrierID == carrierID)
							{
								obj.select.innerHTML += '<option value="' + obj.services[i].ID + '">' + obj.services[i].serviceDescription + '</option>';
							}
						}
					}
					
					YAHOO.util.Event.addListener(shipBySelect, 'change', populateService, obj);
					populateService(null, obj, obj.shipBys[0].shipByID);
					
					var div = document.createElement('div');
					div.setAttribute('id', 'changeCarrierButtons');
					bd.appendChild(div);
					
					new YAHOO.widget.Button({
						id:"carrierSaveButton",
						label:"Save",
						container:div,
						onclick:{fn:function() {
							ShippingAdvisor.ajaxRequest("POST", "ajax/changeCarrier.ajax", {success:function(o){ShippingAdvisor.actionPanel.hide();}}, 'shipBy=' + shipBySelect.value + '&service=' + serviceSelect.value + '&orders=' + YAHOO.lang.JSON.stringify(shippingOrderIDs));
						}}}
					);
				
					new YAHOO.widget.Button({
						id:"carrierCancelButton",
						label:"Cancel",
						container:div,             
						onclick:{fn:function() {ShippingAdvisor.actionPanel.hide();}}}
					);
					

				},
				failure:function(o){
					ShippingAdvisor.actionPanel.hide();
				}
			};
			
			ShippingAdvisor.ajaxRequest("POST", "ajax/changeCarrierDialog.ajax?shippingOrderID=" + shippingOrderIDs[0], callback);
			ShippingAdvisor.actionPanel.render(document.body);
			ShippingAdvisor.actionPanel.show();
		};
		
		this.openDeferShipmentDialog = function(shippingOrderIDs)
		{
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("deferShipment", 
				{
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true
				}
			);
			ShippingAdvisor.actionPanel.setHeader("Defer Shipment");	
			ShippingAdvisor.actionPanel.setBody("Loading...");
			
			var callback = {
				success: function (o) {
					ShippingAdvisor.actionPanel.setBody(o.responseText);
					var calendar = new YAHOO.widget.Calendar("deferShipmentCalendarDiv");
					calendar.render();
					new YAHOO.widget.Button("deferCancelButton").addListener('click', function() {ShippingAdvisor.actionPanel.hide();});
					new YAHOO.widget.Button("deferSaveButton").addListener('click', function() 
						{
							var saveCallback = {
								success: function (o) {
									// fire any events that occurred
									ShippingAdvisor.refreshExpandedRow();
									ShippingAdvisor.actionPanel.hide();
								},
								failure:function(o){
									ShippingAdvisor.actionPanel.hide();
								}
							}
							
							var postData = "timestamp=" +  (calendar.getSelectedDates()[0].getTime() / 1000);
							postData += "&requireConfirmation=" + (YAHOO.util.Dom.get('deferConfirmCheckbox').checked ? 1 : 0);
							postData += "&orders="+ YAHOO.lang.JSON.stringify(shippingOrderIDs);
							ShippingAdvisor.ajaxRequest("POST", "ajax/deferOrders.ajax", saveCallback, postData);
						}
					);

				},
				failure:function(o){
					ShippingAdvisor.actionPanel.hide();
				}
			};
			
			ShippingAdvisor.ajaxRequest("POST", "ajax/deferShipmentDialog.ajax", callback);
			ShippingAdvisor.actionPanel.render(document.body);
			ShippingAdvisor.actionPanel.show();
		};
		
		this.openBackOrderDialog = function(shippingOrderIDs, shippingOrderItemIDs)
		{
			if (!shippingOrderItemIDs)
			{
				shippingOrderItemIDs = new Array();
			}
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("backOrderItems", 
				{
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true
				}
			);
			ShippingAdvisor.actionPanel.setHeader("Backorder Items");
			ShippingAdvisor.actionPanel.setBody("Loading...");
			
			var callback = {
				success: function (o) {
					var obj = YAHOO.lang.JSON.parse(o.responseText);
					ShippingAdvisor.actionPanel.setBody(obj.body);
					var ds = new YAHOO.util.DataSource(obj.data);
					ds.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
					ds.responseSchema = {fields: ["title", "ID", "checked", "quantity", "hasSupplier", "supplierCode"]}; 
					var dt = new YAHOO.ShippingAdvisor.ext.DataView("backOrderItemsTable", [
						{key:"checked", label:"", width:15, formatter:function(elCell, oRecord, oColumn, oData) 
							{
								YAHOO.widget.DataTable.formatCheckbox(elCell, oRecord, oColumn, oData);
								if (oRecord.getData('hasSupplier') == 0)
								{
									YAHOO.util.Dom.getFirstChild(elCell).disabled = true;
								}
							}
						},
						{key:"title", label:"Item", formatter:function(elCell, oRecord, oColumn, oData) 
							{
								var message = (oRecord.getData('hasSupplier') == 0) ? '<br /><span class="error"><a href="suppliers.html">No Supplier Found For Code ' + oRecord.getData('supplierCode') + '</a></span>' : "";
								elCell.innerHTML = oData +  message;
							}},
						{key:"quantity", label:"Quantity", formatter:function(elCell, oRecord, oColumn, oData) 
							{
								YAHOO.widget.DataTable.formatTextbox(elCell, oRecord, oColumn, oData);
								if (oRecord.getData('hasSupplier') == 0)
								{
									YAHOO.util.Dom.getFirstChild(elCell).disabled = true;
								}
							}}], ds);
					dt.originalConfig = {divID:'backOrderItemsTable'};
					dt.subscribe("checkboxClickEvent", function(oArgs){ 
					    var elCheckbox = oArgs.target; 
					    var elRecord = this.getRecord(elCheckbox);
					    if (elCheckbox.checked)
					    {
						this.selectRow(elRecord);
					    }
					    else
					    {
						this.unselectRow(elRecord);
					    }
					    this.getRecordSet().updateKey(elRecord, "checked", elCheckbox.checked);
					}); 
					ShippingAdvisor.dataTables.push({dt:dt});
					if (dt.getRecordSet().getRecords().length == 1 && dt.getRecordSet().getRecords()[0].getData('hasSupplier') == 1)
					{
						ShippingAdvisor.dtSelectAll('backOrderItemsTable');
					}
					else
					{
						var records = ShippingAdvisor.dtGetRows(dt, 'ID', shippingOrderItemIDs);
						for (var i in records)
						{
							if (records[i].getData('hasSupplier') == 1)
							{
								ShippingAdvisor.selectRow(dt, records[i]);
							}
						}
					}
					new YAHOO.widget.Button("backorderCancelButton").addListener('click', function() {ShippingAdvisor.actionPanel.hide();});
					new YAHOO.widget.Button("backorderSaveButton").addListener('click', function() 
						{
							var items = new Array();
							var selected = dt.getSelectedRows();
							var column = dt.getColumn('quantity');
							for (var i in selected)
							{
								var quantity = dt.getTdLinerEl({record:dt.getRecord(selected[i]), column:column}).firstChild.value;
								items.push({itemID:dt.getRecord(selected[i]).getData('ID'), quantity:quantity});
							}
							var saveCallback = {
								success: function () {
									ShippingAdvisor.actionPanel.hide();
									ShippingAdvisor.refreshExpandedRow();
								},
								failure:function(o){
									ShippingAdvisor.actionPanel.hide();
								}
							}
							if (selected.length > 0)
							{
								var postData = "items="+ YAHOO.lang.JSON.stringify(items);
								ShippingAdvisor.ajaxRequest("POST", "ajax/backorderItems.ajax", saveCallback, postData);
							}
							else
							{
								ShippingAdvisor.actionPanel.hide();
							}
						}
					);

				},
				failure:function(o){
					ShippingAdvisor.actionPanel.hide();
				}
			};
			
			var postData = "orders=" + YAHOO.lang.JSON.stringify(shippingOrderIDs);
			ShippingAdvisor.ajaxRequest("POST", "ajax/backorderItemsDialog.ajax", callback, postData);
			ShippingAdvisor.actionPanel.render(document.body);
			ShippingAdvisor.actionPanel.show();
		};
		
		this.openSplitOrderDialog = function(shippingOrderID)
		{
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("splitOrderItems", 
				{
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true
				}
			);
			ShippingAdvisor.actionPanel.setHeader("Split Order");	
			ShippingAdvisor.actionPanel.setBody("Loading...");
			
			var callback = {
				success: function (o) {
					var obj = YAHOO.lang.JSON.parse(o.responseText);
					ShippingAdvisor.actionPanel.setBody(obj.body);
					var ds = new YAHOO.util.DataSource(obj.data);
					ds.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
					ds.responseSchema = {fields: ["title", "ID", "checked"]}; 
					var dt = new YAHOO.widget.DataTable("splitOrderItemsTable", [
						{key:"checked", label:"", width:15, formatter:YAHOO.widget.DataTable.formatCheckbox},
						{key:"title", label:"Item"}], ds);
					dt.subscribe("checkboxClickEvent", function(oArgs){ 
					    var elCheckbox = oArgs.target; 
					    var elRecord = this.getRecord(elCheckbox);
					    if (elCheckbox.checked)
					    {
						this.selectRow(elRecord);
					    }
					    else
					    {
						this.unselectRow(elRecord);
					    }
					    this.getRecordSet().updateKey(elRecord, "checked", elCheckbox.checked);
					}); 
					ShippingAdvisor.dataTables.push({dt:dt});
					new YAHOO.widget.Button("splitorderCancelButton").addListener('click', function() {ShippingAdvisor.actionPanel.hide();});
					new YAHOO.widget.Button("splitorderSaveButton").addListener('click', function() 
						{
							var itemIDs = ShippingAdvisor.getSelectedOrders("backOrderItemsTable", "ID");
							var saveCallback = {
								success: function () {
									// remove orders from table
									ShippingAdvisor.actionPanel.hide();
									ShippingAdvisor.refreshAllDataTables();
								},
								failure:function(o){
									ShippingAdvisor.actionPanel.hide();
								}
							}
							
							var postData = "shippingOrderID=" + shippingOrderID + "&items="+ YAHOO.lang.JSON.stringify(itemIDs);
							ShippingAdvisor.ajaxRequest("POST", "ajax/splitOrder.ajax", saveCallback, postData);
						}
					);

				},
				failure:function(o){
					ShippingAdvisor.actionPanel.hide();
				}
			};
			
			var postData = "order=" + shippingOrderID
			ShippingAdvisor.ajaxRequest("POST", "ajax/splitOrderDialog.ajax", callback, postData);
			ShippingAdvisor.actionPanel.render(document.body);
			ShippingAdvisor.actionPanel.show();
		};
		
		this.openCancelOrderDialog = function(shippingOrderIDs)
		{
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("cancelOrders", 
				{
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true,                                       
					width:400
				}
			);
			ShippingAdvisor.actionPanel.setHeader("Cancel Orders");	
			ShippingAdvisor.actionPanel.setBody('Loading...');
			
			var callback = {
				success: function (o) {
					ShippingAdvisor.actionPanel.setBody(o.responseText);
					new YAHOO.widget.Button("cancelOrderCancelButton").addListener('click', function() {ShippingAdvisor.actionPanel.hide();});
					new YAHOO.widget.Button("cancelOrderSaveButton").addListener('click', function() {
						var callback = {
							success:function(o){
								var obj = YAHOO.lang.JSON.parse(o.responseText);
								ShippingAdvisor.dtRemoveRows({divID:'content', shippingOrderIDs:obj.success, key:'ID'});
								ShippingAdvisor.actionPanel.hide();
							},
							failure:function(o){
								ShippingAdvisor.actionPanel.hide();
							}
						};
						var postData = "orders=" + YAHOO.lang.JSON.stringify(shippingOrderIDs) + "&comment=Cancelled : " + YAHOO.util.Dom.get('cancelOrderTextArea').value;
						ShippingAdvisor.ajaxRequest("POST", "ajax/setOrdersInactive.ajax", callback, postData);
					});

				},
				failure:function(o){
					ShippingAdvisor.actionPanel.hide();
				}
			};
			var postData = "orders=" + YAHOO.lang.JSON.stringify(shippingOrderIDs);
			ShippingAdvisor.ajaxRequest("POST", "ajax/cancelOrderDialog.ajax", callback, postData);
			ShippingAdvisor.actionPanel.render(document.body);
			ShippingAdvisor.actionPanel.show();
		};
		
		this.openCustomerCarrierDialog = function(shippingOrderID)
		{
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("changeConsignment", 
				{
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true
				}
			);
			ShippingAdvisor.actionPanel.setHeader("Change Selected Carrier / Class");
			ShippingAdvisor.actionPanel.setBody('<table><tr><td>Carrier:</td><td><input type="text" id="changeCarrierInput"></input></td></tr><tr><td>Class:</td><td><input type="text" id="changeClassInput"></input></td></tr></table><input type="button" id="consignmentSaveButton" value="Save"/><input type="button" id="consignmentCancelButton"/ value="Cancel">');
			
			ShippingAdvisor.actionPanel.render(document.body);
			ShippingAdvisor.actionPanel.show();
			new YAHOO.widget.Button("consignmentCancelButton").addListener('click', function() {ShippingAdvisor.actionPanel.hide();});
			new YAHOO.widget.Button("consignmentSaveButton").addListener('click', function() {
				var callback = {
					success:function(o){
						ShippingAdvisor.refreshExpandedRow();
						ShippingAdvisor.actionPanel.hide();
					},
					failure:function(o){
						ShippingAdvisor.actionPanel.hide();
					}
				};
				var postData = "shippingOrderID=" + shippingOrderID + "&shippingCarrier=" + YAHOO.util.Dom.get('changeCarrierInput').value + "&shippingClass=" + YAHOO.util.Dom.get('changeClassInput').value;
				ShippingAdvisor.ajaxRequest("POST", "ajax/saveCustomerCarrier.ajax", callback, postData);
			});

			
			
		};
		
		this.toggleSearchDialog = function()
		{
			if (ShippingAdvisor.searchDialog && ShippingAdvisor.searchDialog.element)
			{
				ShippingAdvisor.searchDialog.destroy();
				return;
			}
			var items = ShippingAdvisor.menuBar.getItems();
			var menuEl;
			for (var i in items)
			{
				if (items[i].cfg.config.text.value == 'Search')
				{
					menuEl = items[i].element;
				}
			}
			ShippingAdvisor.searchDialog = new YAHOO.widget.Overlay("searchDialog", 
			{
				context:[menuEl, "tl", "bl"],
				width:340
			});
			ShippingAdvisor.searchDialog.setBody('<form action="/cms/search.html" method="GET">Find <input type="text" id="searchText" name="searchText"/> in <select name="searchField"><option value="orderDisplayID">Order ID</option><option value="customerName">Customer Name</option>		<option value="customerEmail">Customer Email Address</option><option value="userID">Customer User ID</option>		<option value="SKU">SKU</option>		<option value="trackingNumber">Tracking Number</option></select><br/><input style="float:right" type="submit" id="searchButton" value="Search"/></form><span style="float:left;font-size:11px;position:relative;top:10px;"><a href="/cms/search.html?switchTab=1">Browse History</a></span>');
			ShippingAdvisor.searchDialog.render(document.body);
			YAHOO.util.Dom.get('searchText').focus();
		}
		
		this.openReminderDialog = function()
		{
			ShippingAdvisor.actionPanel = new YAHOO.widget.Panel("addReminder", 
				{
					fixedcenter: true, 
					constraintoviewport: true, 
					underlay:"shadow", 
					close:true, 
					visible:false, 
					draggable:true,
					modal:true
				}
			);
			ShippingAdvisor.actionPanel.setHeader("Add Reminder");	
			ShippingAdvisor.actionPanel.setBody('<table><tr><td><div id="reminderCalendarDiv"></div></td><td>Reminder Text:<br/><form id="addReminderForm"><textarea id="addReminderDialogText" rows="10" name="text"></textarea></form></div></td></tr><tr><td colspan="2" align="right"><div id="addReminderDialogButtons"></div></td></tr></table>');
			ShippingAdvisor.actionPanel.render(document.body);
			tinyMCE.settings = {
					mode : "none",
					theme : "advanced",
					theme_advanced_toolbar_location : "top",
					theme_advanced_buttons1 : "bold,italic,underline,fontsizeselect,link,unlink",
					theme_advanced_buttons2 : "",
					theme_advanced_buttons3 : "",
					plugins : "inlinepopups",
					dialog_type : "modal"
			};
			
			tinyMCE.execCommand('mceAddControl', false, 'addReminderDialogText');
			ShippingAdvisor.actionPanel.hideEvent.subscribe(function(e) {
				tinyMCE.execCommand('mceRemoveControl', false, 'addReminderDialogText');
			});
			ShippingAdvisor.actionPanel.show();
			var now = new Date();
			var calendar = new YAHOO.widget.Calendar("reminderCalendarDiv", {mindate:now, selected:now.getMonth() + '/' + now.getDate() + '/' + now.getFullYear()});
			calendar.render();
			new YAHOO.widget.Button({
				container:"addReminderDialogButtons",
				label:'Cancel'
			}).addListener('click', function() {ShippingAdvisor.actionPanel.hide();});
			
			new YAHOO.widget.Button({
				container:"addReminderDialogButtons",
				label:'Save'
			}).addListener('click', function() 
				{
					var saveCallback = {
						success: function (o) {
							ShippingAdvisor.actionPanel.hide();
						},
						failure:function(o){
							ShippingAdvisor.actionPanel.hide();
						}
					}
					tinyMCE.triggerSave();
					var postData = "timestamp=" +  (calendar.getSelectedDates()[0].getTime() / 1000);
					postData += "&" + YAHOO.util.Connect.setForm(YAHOO.util.Dom.get('addReminderForm'));
					ShippingAdvisor.ajaxRequest("POST", "ajax/addReminder.ajax", saveCallback, postData);
				}
			);			
			
		};
		
		
		
		this.printInvoice = function(shippingOrderIDs)
		{
			window.open('printInvoicesFrames.print?orders='+YAHOO.lang.JSON.stringify(shippingOrderIDs), 'printInvoice');
		}
		
		this.dataTables = new Array();
	}
	
	
	
});

