
	// Add some native functions to the string object
	Object.extend(String.prototype, {
		isDate: function(){ return /^\d{1,2}[\/]\d{1,2}[\/]\d{2,4}$/.test(this); },
		isTime: function(){ return /^\d{1,2}[:]\d{2}$/.test(this); },
		isNumeric: function(){ return /^\d+$/.test(this); },
		formatNumber: function(){ a = this; while (/(\d+)(\d{3})/.test(a)) a = a.replace(/(\d+)(\d{3})/, '$1,$2'); return a; }
	});

	Element.addMethods({
		// Element.addChild is an easy way to create an extended element with the specified attributes
		// and add it to the parent node. The newly created child node is returned.
		// Usage: $(element).addChild('td', { width: '25%', align: 'center' });
		addChild: function( element, tagName, attributes ) {
			var c = new Element(tagName, attributes || {}); $(element).appendChild(c); return c;
		},

		// Element.removeChildren is a simple way to remove all child nodes from an element.
		// This method returns an extended reference to the parent node.
		// Usage: $(element).removeChildren();
		removeChildren: function( element ) { $A($(element).childNodes).collect(Element.remove); return $(element); },

		addOverlay: function( element, options ) {
			element = $(element); options = options || {};

			var overlay = $(document.createElement('div'));
			document.getElementsByTagName('body').item(0).appendChild(overlay);

			overlay.setOpacity(options.opacity || 0.15);
			overlay.setStyle({
				position: 'absolute', background: '#' + (options.color || '000'),
				zIndex: options.zIndex || parseInt(element.getStyle('zIndex')) + 1
			}).clonePosition(element);
			return overlay;
		},

		center: function( element ) {
			element = $(element).absolutize();
			var d = element.getOffsetParent().getDimensions();

			return element.setStyle({
				top: ( ( d.height - element.getHeight() ) / 2 ) + 'px',
				left: ( ( d.width - element.getWidth() ) / 2 ) + 'px'
			});
		},

		removeEvent: Event.stopObserving // Add Event.removeEvent method to Element
	});

	var cfg = {}; // Create CFG namespace

	Object.extend(cfg, { calendar: {} }); // Add calendar to CFG namespace
	Object.extend(cfg.calendar, {
		show: function( target ) { // Open calendar view window
			var calendar = window.open("cfDateSelect.cfg?fieldName=" + target, "CalendarWindow", "width=200,height=125");
			if ( calendar ) calendar.focus();
		}
	});

	Object.extend(cfg, { banner: {} }); // Add banner to CFG namespace

	Object.extend(cfg.banner, { search: {} }); // Add search to CFG banner
	Object.extend(cfg.banner.search, {
		tabs: [],

		addTab: function( id, text, phrase, url ) { this.tabs.push({ 'id': id, 'text': text, 'phrase': phrase, 'url': url, selected: false }); },
		drawTabs: function() {
				var tRow = $('bannerSearchTabs').removeChildren();
				var selectFirst = true, self = this, i = 0;

				this.tabs.each(function(t){ // Add tabs to page
					if ( $('searchBarType') && t.id == $F('searchBarType') ) t.selected = true;
					var tCell = tRow.addChild('td', { 'id': t.id, align: 'center' }).addClassName('pointer').update( t.text );
					tCell.observe('click', function(){ this.selectTab( t.id ); }.bindAsEventListener(self));
					tCell.observe('focus', function(){ this.blur(); }.bindAsEventListener(tCell));
					if ( ++i < self.tabs.length ) tRow.addChild('td', { align: 'center' }).setStyle({ paddingBottom: 0, paddingTop: 0 }).update('|');
				});

				this.tabs.each(function(t){ if ( t.selected ){ self.selectTab( t.id ); selectFirst = false; } });
				if ( selectFirst && this.tabs.length > 0 ) this.selectTab( this.tabs[0].id );
		},

		selectTab: function( tab ) {
			try {
				if (typeof(tab) != 'string') tab = $(tab).id;

				this.tabs.each(function(t){
					t.selected = ((t.id != tab) ? false : true);
					if ($(t.id)) {
						if ( t.selected ) {
							$(t.id).setStyle({ fontWeight: 'bold' }).addClassName('primaryColor');
						} else {
							$(t.id).setStyle({ fontWeight: 'normal' }).removeClassName('primaryColor');
						}
					} else {
						writeToConsole('Could not find tab: ' + t.id);
					}
				});
				this.refreshPhrase();
				$('searchBarType').value = tab;
			} catch(e) {
				writeToConsole(e);
			}
		},

		clearSearch: function() { if ( this.tabs.pluck('phrase').indexOf( $F('searchText') ) > -1 ) $('searchText').value = ''; },
		refreshPhrase: function() {
			var text = $F('searchText');
			var tab = this.tabs.find(function(t){ return t.selected });
			var phrase = this.tabs.find(function(t){ return t.phrase == text; });
			if ( tab != undefined && (phrase != undefined || text.blank()) ) $('searchText').value = tab.phrase;
		}
	});

	Object.extend(cfg.banner, { cart: {} }); // Add cart to CFG banner
	Object.extend(cfg.banner.cart, {
		hide: function() {
			var cart = $('cartSlider');
			if (cart.isMoving || !cart.isShown) return false;

			var top = parseInt(cart.getStyle('top'));
			var dimensions = cart.getDimensions();

			new Effect.MoveBy(cart, -top - dimensions.height, 0, {
				beforeStart: function(){ $('cartSlider').isMoving = true; },
				afterFinish: function(){ $('cartSlider').isMoving = false; $('cartSlider').isShown = false; }
			});
			return true;
		},

		show: function() {
			this.positionCartSlider();
			var cart = $('cartSlider');
			if (cart.isMoving || cart.isShown) return false;

			var top = parseInt(cart.getStyle('top'));
			new Effect.MoveBy(cart, 22 - top, 0, {
				beforeStart: function(){ $('cartSlider').isMoving = true; },
				afterFinish: function(){ $('cartSlider').isMoving = false; $('cartSlider').isShown = true; }
			});
			return true;
		},

		positionCartSlider: function() {
			var cart = $('cartSlider');
			cart.isMoving = false; cart.isShown = false;
			var dimensions = cart.getDimensions();
			cart.setStyle({ top: -dimensions.height + 'px', left: $('pageContainer').getDimensions().width - dimensions.width + 'px' });
			$('cartSlider').observe('mouseup', function(e){ Event.stop(e); });
		},

		showTimed: function( seconds ) {
			var self = this; seconds = seconds || 6; self.show(); setTimeout(function(){ self.hide(); }, seconds * 1000);
		},

		adjustBannerDisplay: function( items ) {
			try {
				if ( items > 0 ) {
					var icon = $('cartIcon').removeChildren().addChild('img', { src: '/clientassets/v9/stockImages/cfgSearchCart.gif' }).addClassName('pointer');
					var target = $('cartLink').update('<span onclick="javascript: cfg.banner.cart.show();" class="bold noDecoration pointer">Shopping Cart</span>');
					$('cartItemCount').update('&nbsp;|&nbsp;' + items + ' items in cart');
					Event.observe(icon, 'click', cfg.banner.cart.show);
				} else {
					var anchor = $('cartIcon').removeChildren().addChild('a', { href: 'createOrder.cfg' });
					var icon = anchor.addChild('img', { src: '/clientassets/v9/stockImages/cfgSearchCart.gif', border: '0' });
					var target = $('cartLink').update('<a href="createOrder.cfg" class="bold noDecoration">Shopping Cart</a>');
					$('cartItemCount').update();
				}
			} catch(e) {
				writeToConsole(e);
			}
		},

		updateContents: function( response, json, options ) {
			try {
				var tBody = $('cartSlider_ItemList').removeChildren(); // Refresh slider contents
				var premiumCost = 0;

				json.each(function(i){
					var tRow = tBody.addChild('tr').addClassName('sc');
					var tCell = tRow.addChild('td').update( i.quantity );
					if ( i.customstate == '' ) {
						var tCell = tRow.addChild('td', { title: i.description }).update( i.sku );
					} else {
						var tCell = tRow.addChild('td', { title: i.description }).update( i.sku + ' (' + i.customstate + ')' );
					}
					if ( i.premium > 0 ) premiumCost += (i.price * i.quantity);
				});

				if ( premiumCost > 0 ) {
					//$('cartPremiumCost').show(); $('cartPremiumCostTotal').update('Premium Cost: $' + String(premiumCost).formatNumber());
					// rounding to 2 decimal places isn't compatible with the formatNumer function that adds commas
					$('cartPremiumCost').show(); $('cartPremiumCostTotal').update('Premium Cost: $' + String(Math.round(premiumCost*100)/100));
				} else {
					$('cartPremiumCost').hide();
				}

				this.adjustBannerDisplay( json.size() );
			} catch(e) {
				writeToConsole(e);
			}
		},

		refreshContents: function() {
			var self = this; // Bind reference to cart and not ajax object

			new mxAjax.Data({
				paramArgs: new mxAjax.Param('/cfgroot/mxAjax/libraries/general.cfg', { cffunction:'getCartContents', param: 'id=' + this.id }),
				handler: this.updateContents.bind(self), executeOnLoad: true
			});
		}
	});

	Object.extend(cfg, { alerts: {} }); // Add alerts to CFG namespace
	Object.extend(cfg.alerts, {
		validation: {
			showError: function( error ) {
				alert(
					'You failed to correctly fill in your:' +
					'\n\t-' + ((typeof error != 'string') ? error.join('\n\t-') : error) +
					'\n\nPlease re-enter and submit again!'
				);
			}
		}
	});

	function debug(m) { if (typeof console != 'undefined') { console.log(m); } else { alert('An error has occured: ' + m); } } // Some debugging tools for firebug
	function writeToConsole( m ) { if (typeof console != 'undefined') { console.log(m); } }
	function dumpResponse( r, j, o ) { dump(j); }

	function toggleElement( target ){ $(target).toggle(); }
	function toggleNextSibling( element ) { return $(element).next().toggle(); }

	function openWin( url, name, features ) { return window.open( url, name, features ); }

	function ShowCalendar(FormName, FieldName) {
		window.open("cfDateSelect.cfg?FormName=" + FormName + "&FieldName=" + FieldName, "CalendarWindow", "width=200,height=125");
	}

	function setupMouseovers() { // Add mouseover and mousedown actions
		$A($$('img[hsrc|dsrc]','input[type=image][hsrc|dsrc]')).each(function(el) {
			el.n = new Image(); el.n.src = el.src;

			if ( el.hasAttribute('hsrc') ) { // Add mouseover image
				el.h = new Image(); el.h.src = el.readAttribute('hsrc');
				el.observe('mouseover', function(){ this.src = this.h.src; }.bindAsEventListener(el));
				el.observe('mouseout', function(){ this.src = this.n.src; }.bindAsEventListener(el));
			}

			if ( el.hasAttribute('dsrc') ) { // Add mousedown image
				el.d = new Image(); el.readAttribute('dsrc');
				el.observe('mousedown', function(){ this.src = this.d.src; }.bindAsEventListener(el));
				el.observe('mouseup', function(){ this.src = this.n.src; }.bindAsEventListener(el));
			}
		});
	}
	
	
	// Used for Converting Decimal NCR 2 CP
	
	var decDigit = { 0:1, 1:1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1 };
	
	function convertDecNCR2CP ( textString ) {
		 CPstring = '';
		 textString += ' ';
		 var tempString = '';
		 var charStr = '';
		
		 // first convert whole string to characters
		 for (var i=0; i<textString.length-1; i++) {
		 if (i<textString.length-3 && textString.charAt(i) == '&'
		 && textString.charAt(i+1) == '#' && textString.charAt(i+2) in decDigit) { // &#1
		 tempString = '';
		 i += 2;
		 while (i<textString.length-1 && textString.charAt(i) in decDigit) {
		 tempString += textString.charAt(i);
		 i++;
		 }
		 // only convert sequence to character if terminated by ;
		 if (textString.charAt(i) == ';') {
		 charStr += convertCP2Char(parseInt(tempString).toString(16));
		//alert(tempString);
		 }
		 else { charStr += '&#'+tempString; i--;}
		 }
		 else {
		 charStr += textString.charAt(i);
		 }
		 }
		
		return charStr;
		
	 }
	 	 
	 function convertCP2Char ( textString ) {
		 var outputString = '';
		 textString = textString.replace(/^\s+/, '');
		 if (textString.length == 0) { return ""; }
		 textString = textString.replace(/\s+/g, ' ');
		 var listArray = textString.split(' ');
		 for ( var i = 0; i < listArray.length; i++ ) {
		 var n = parseInt(listArray[i], 16);
		 if (n <= 0xFFFF) {
		 outputString += String.fromCharCode(n);
		 } else if (n <= 0x10FFFF) {
		 n -= 0x10000
		 outputString += String.fromCharCode(0xD800 | (n >> 10)) + String.fromCharCode(0xDC00 | (n & 0x3FF));
		 } else {
		 outputString += 'convertCP2Char error: Code point out of range: '+dec2hex(n);
		 }
		 }
		 return( outputString );
	}
	

	Event.observe(window, 'load', setupMouseovers);

	function $RF( radioName ) {  // Find value of selected radio option
		var r = $A($$('input[name=' + radioName + ']')).find(function(r){ return r.checked; });
		if ( r != 'undefined' ) return $F(r); return false;
	}
	
	function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
	}	

	function readCookie(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i=0;i < ca.length;i++) {
			var c = ca[i];
			while (c.charAt(0)==' ') c = c.substring(1,c.length);
			if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
		}
		return null;
	}
	
	function eraseCookie(name) {
		createCookie(name,"",-1);
	}
	
