(function () {
	var 
		earth = 3960.0,
		radPerDeg = Math.PI/180.0;

	Math.deltalatFromMiles = function (miles) {
		return miles/radPerDeg/earth;
	}
	Math.deltalngFromMiles = function (lat, miles) {
		r = earth*Math.cos(lat*radPerDeg);
		return miles/radPerDeg/r;
	}
	Math.getZoomLevelFromRadius = function (lat, rad, bWidth, bHeight) {
		//lat in degrees, rad in miles, bWidth / bHeight in px
		var 
			dLat = Math.deltalatFromMiles(rad),
			dLng = Math.deltalngFromMiles(lat, rad),
			height = 2*dLat,
			width = 2*dLng;
		return Math.floor(Math.max(
			Math.log(180*bHeight/256/width)/Math.log(2),
			Math.log(360*bWidth/256/height)/Math.log(2)
		));
	}
})();
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
}
String.prototype.ltrim = function() {
	return this.replace(/^\s+/,"");
}
String.prototype.rtrim = function() {
	return this.replace(/\s+$/,"");
}

/*
*	Discrete value slider
*	Depends on an existent structure:
*		<backingElement style="position: relative">
*			<markerElement style="position: absolute" />
*		</backingElement>
*	There can be other elements within the backingElement; the constructor is called on the 
*		marker; the backing is derived as its offsetParent
*	The direction of the slider can be overridden below, but is guessed by the following rule:
*		Whichever dimension of the backing can hold the most markers
*	CSS-controlled parameters:
*		(px) font-size: sets the pixel width of each step on the slider
*		(em) left/top: sets the starting position of the slider
*	@author	Bryan Elliott
*	
*	@param	element	The marker element of the slider
*	@param	object		The parameters to override on the slider
*		(bool)		direction	Df.TickSlider.Horizontal or Df.TickSlider.Vertical	default: see above
*		(string)	cursor		The cursor the marker should use when you hover over it	default: IE?'hand':'pointer'
*		(string)	movingCursor	The cursor the marker should have when dragging		default: horizontal?'n-size':'w-size'
*	(array/function)	throwLimits	[min, max], or a function that constrains a number		default: see code
*		(int)		tickValue	pixel spacing between valid spots on the slider		default: element.style.fontSize
*		(int)		startPosition	starting position of the marker on the slider		default: derived from marker position
*		(function)	onChange	callback for when the marker is dropped
*	@see	class Df.TickSlider
*/
Df.TickSlider = Class.create(Df.Drag,{
	initialize: function($super, element, pars){
		var	
			draggable=this,
			_1,
			backing = Element.getOffsetParent(element),
			pointer = Prototype.Browser.IE?'hand':'pointer',
			offpar = Element.getOffsetParent(backing),
			dir = (!!pars && typeof pars.direction !== 'undefined')?
				pars.direction:
				backing.offsetWidth / element.offsetWidth > backing.offsetHeight / element.offsetHeight,
			move = dir?'w-resize':'n-resize',
			offsz = dir?'offsetWidth':'offsetHeight',
			pos = dir?'left':'top',
			offpos = dir?'offsetLeft':'offsetTop',
			offorig = backing[offpos],
			scroll = dir?'scrollLeft':'scrollTop',
			evdir = dir?'pointerX':'pointerY';
		while (offpar != document.body) {
			offorig += offpar[offpos];
			offpar = Element.getOffsetParent(offpar);
		}
		
		element.style.cursor = pointer;
		
		var defaults = {
			direction: dir,
			cursor: pointer,
			movingCursor: move,
			throwLimits: function (e) {
			    var 
				min = 0,
				max = parseInt(backing[offsz]) - parseInt(element[offsz]);
			    return Math.max(min,Math.max(min,e));
			},
			tickValue: _1=parseInt(element.getStyle('font-size')),
			startPosition: element[offpos] / _1,
			onChange: function () {}
		};
		Object.extend(defaults, pars);
		if (defaults.throwLimits instanceof Array) {
			var lims = defaults.throwLimits;
			defaults.throwLimits = function (e) {
				var 
					min = Math.min(lims[0], lims[1]),
					max = Math.max(lims[0],lims[1]);
				return Math.max(max,Math.max(min,e));
			}
		}
		var dragOptions = {
			onDrag: function (dummy, event) {
				//TODO: scroll position (as well as nested scrolls) MAY impact apparent mouse position.  Browser-check this.
				var curPos = defaults.throwLimits(Event[evdir](event) - offorig - this[offsz] / 2);
				this.setCurrentIndex(Math.round(curPos / defaults.tickValue));
			}.bind(element),
			onStart: function(event){
				this.style.cursor = move;
			}.bind(element),
			onStop: function (event) {
				this.style.cursor = defaults.cursor;
				this.update();
			}.bind(element),
			tickValue: _1,
			startPosition: defaults.startPosition,
			dirX: dir?defaults.throwLimits:function () {return 0;},
			dirY: dir?function () {return 0;}:defaults.throwLimits
		};
		$super(element, dragOptions);
		Object.extend(this, dragOptions);
		Object.extend(element, {
			currentValue: _1 = Math.round(element.offsetLeft / defaults.tickValue),
			currentIndex: _1
		});
		var callbacks = {
			setCurrentValue: function (value) {
				if (!!defaults.values) {
					for (var i = 0; i < defaults.values.length; i++)
						if (defaults.values[i]==value) break;
					if (i == defaults.values.length) return false;
					this.currentValue = defaults.values[i];
					return element.setCurrentIndex(i);
				} else
					return element.setCurrentIndex(value);
			},
			setCurrentIndex: function (index) {
				if (index != Math.round(defaults.throwLimits(index * defaults.tickValue)/defaults.tickValue))
					return false;
				if (!!defaults.values) {
					if (index >= defaults.values.length)
						return false;
					this.currentValue = defaults.values[index];
				} else {
					this.currentValue = index;
				}
				this.style[pos] = (this.currentIndex = index)+'em';
				return index;
			}.bind(element),
			moveIndex: function (amount) {
				this.setCurrentIndex(this.currentIndex+amount);
			}.bind(element),
			update: function () {
				defaults.onChange(this.currentValue, this.currentIndex);
			}.bind(element)
		};
		Object.extend(this, callbacks);
		Object.extend(element, callbacks);
		if (defaults.values instanceof Array)
			element.currentValue = defaults.values[element.currentIndex];
		defaults.onChange(this.currentValue, this.currentIndex);
		return this;
	}
});
Df.TickSlider.Horizontal = true;
Df.TickSlider.Vertical = false;
/* End definition: Df.TickSlider */
Event.observe(window,'load', function(e){
	GUnload();
	GMap.imgName = (function () {
		var imgName = null;
		return function imgName(marker) {
			if (!!imgName) return imgName;
			for (var i in marker) //attribs of marker
				if (!!marker[i]) //non null
					if (/^mtgt_unnamed_\d+$/.test(marker[i].id)) {//and an id matching ^mtgt_unnamed_\d+$
						imgName=i;
						return imgName
					}
		}
	})();
});

Ajax.Responders.register({
	onCreate: function(){
		Loader.on();
	},

	onComplete: function() {
		if(Ajax.activeRequestCount == 0){
			Loader.off();
		}
	},
	
	onError: function(e,f){
		storeLocator.msg({dataString:f})
		Loader.off();
	},
	
	onException: function(e,f){
		storeLocator.msg({dataString:f});
		Loader.off();
	}
});

var Loader = {
	on: function(){
		if($('sl_loader')){
			$('sl_loader').style.display = 'block';
		}
	},
	
	off: function(){
		if($('sl_loader')){
			$('sl_loader').style.display = 'none';
		}
	},
	
	follow: function(e){
		if($('sl_loader')){
			var loader = $('sl_loader');
			loader.style.left = e.pointerX()  + 13 + 'px';
			loader.style.top = e.pointerY()  + 13 + 'px';
		}
	}
};

/*********************************/
var storeLocator = {
	
	//page scope variables
	vars: {
		storeHeight: 130,
		storesPerPage: 3,
		pageMultiplier: 50,
		zoom: 11,
		minZoomLevel: 3,
		maxZoomLevel: 17,
		mapControler:false,
		
		map: false,
		marker: true,
		currentPageVar: false,
		stores: [],
		totalPages: false,
		address: false,
		miles: true,
		slider: null,
		sliderAry:[],
		initialLoad: true,
		storeAvail: false
	},
	
	services: {
		store: '/storeLocServ'
	},
	
	//base parameters
	pars: {
		operation:'coSearch',
		lat:38.5,
		lon:-90,
		numResults:100,
		mnlt:false,
		mxlt:false,
		mnln:false,
		mxln:false,
		token:'MAUR',
		heavy: true
	},
	
	//recent request caches
	cache: {
		geo: {count:50,recs:[{call:false,response:{lat:false,lon:false}}]},
		store: {count:10,recs:[{call:false,response:false}]}
	},
	
	stopReturn: function(event){
		if(event.keyCode == 13){
			storeLocator.updateMap()
			return false
		}else{
			return undefined
		}
	},
	
	resetPage: function(obj){
		//clear points
		storeLocator.map.clearMarkers(storeLocator.vars.map,storeLocator.vars.stores)
		
		storeLocator.vars.currentPageVar = 1
		
		$('ResultHeader').update();
		$('ResultList').update();
		$('ResultFooter').update();
		//$('errorBox').update();
		//$('errorBox').style.display = 'none';
		
	},
	
	//message handling
	msg: function(para){
		//$('errorBox').style.display = 'block'
		//$('errorBox').update(para.dataString)
	},
	degrade: false,
	buildAddress: function(){
		var string = '';
		var address = $('address').value.strip();
		var city = $('city').value.strip();
		var state = $('state').value.strip();
		var zip = $('postalCode').value.strip();
		string += address + " " + city + " " + state + " " + zip;
		string = string.trim();
		
		if(string.length > 0){
			//validation
			if(!string){
				storeLocator.resetPage();
				storeLocator.msg({dataString:'Please enter an address that our system can search for.'});
			}
			
			if(string.match(/0/g)){
				if(string.length == string.match(/0/g).length){
					string='';
					storeLocator.resetPage();
					storeLocator.msg({dataString:'Search Not Recognized'});
				}	
			}
		} else {
			storeLocator.resetPage();
			storeLocator.msg({dataString:'Please enter a Street, City and State OR a Zip Code.'});
		}
		return string;
	},
	
	//START OF MAP UPDATE CASCADE
	updateMap: function(){
		if(GBrowserIsCompatible()) {
			
			//clear bubble
			storeLocator.map.bubble.hide()
			
			//populate global pars object
			storeLocator.vars.address = storeLocator.buildAddress()

			if(!storeLocator.vars.address){
				return	
			}
			
			//scan cache
			var cached = storeLocator.cache.geo.recs.detect(function(v,i){
				if(storeLocator.vars.address == v.call){
					//update lat and lng
					storeLocator.pars.lat = v.response.lat
					storeLocator.pars.lon = v.response.lon
					return true
				}else{
					return false
				}
			});
			
			if(cached){
				storeLocator.setLocation()
			}else{
				storeLocator.getLocation()
			}
		}
	},
	
	getLocation: function(txtAddress) {
		if (storeLocator.degrade) return true;
		var geocoder = new GClientGeocoder();
		if (!txtAddress) {
			var addr = $$('.addressRequest')[0];
			addr.focus();
			txtAddress = addr.value==''?null:addr.value;
			addr.blur();
		}
		if (txtAddress == null) {
			return storeLocator.msg({dataString: 'Nothing to locate'});
        }
        geocoder.getLatLng(txtAddress,function(point) {
			//validation
            if (point == null) {
				/* fix for QC #61311 */
                storeLocator.resetPage();
                storeLocator.msg({dataString:'Sorry, no locations were found in this area'})
                $('ResultHeader').update('<h2 class="welcome">Sorry, no locations were found.</h2>')
                $('ResultList').update('<p>Sorry, no locations were found in this area. <strong style="color:#d81027">Tip: Try zooming out further</strong></p><p>While we have a vast network of stores, no stores were found using your current selection.</p><p><strong>Please refine your search by:</strong><br /><br />- Altering your search parameters<br />- Expanding your zoom level</p>')
				return false;
	} else {
				//load results in cache
				storeLocator.cache.geo.recs.unshift({call:storeLocator.vars.address,response:{lat:point.lat(),lon:point.lng()}});
				//check size of cache and remove if nessessary
				if(storeLocator.cache.geo.recs.length>storeLocator.cache.geo.count) storeLocator.cache.geo.recs.pop();
				//set new points
				//Determine zoom level for position
				var zoom = Math.getZoomLevelFromRadius(
					point.lat(),
					parseFloat($('radius').value),
					(_=$('map')).offsetWidth,
					_.offsetHeight
				);
				storeLocator.slider.setCurrentValue(zoom);
				storeLocator.slider.update();
				storeLocator.pars.lat = point.lat();
				storeLocator.pars.lon = point.lng();
				//set new location on map
				return storeLocator.setLocation();
			}
		});
	},
	
	setLocation: function(point){
		if(!point)
			point = new GLatLng(storeLocator.pars.lat,storeLocator.pars.lon)
		
		GEvent.clearInstanceListeners(storeLocator.vars.map)
		
		//pan to center of address
		storeLocator.vars.map.setCenter(point)
		
		window.setTimeout(function(){
			storeLocator.map.addEvents(storeLocator.vars.map)
		},100)
		
		storeLocator.vars.miles = true
		
		if(storeLocator.vars.initialLoad == true){
			storeLocator.map.cachedSetup(storeLocator.vars.map,false,false)
			storeLocator.vars.initialLoad = false
			storeLocator.vars.map.savePosition()
		}
		
		//set map bounds for stores
		storeLocator.setBounds()
	},
	
	getFromHere: function(){
		var point = storeLocator.vars.map.getCenter();
		
		//set new points
		storeLocator.pars.lat = point.lat()
		storeLocator.pars.lon = point.lng()
		
		//set map bounds for stores
		storeLocator.setBounds()
	},
	
	setBounds: function(){
		var bounds = storeLocator.vars.map.getBounds()
		storeLocator.pars.mnlt = Math.min(bounds.getSouthWest().lat(),bounds.getNorthEast().lat())
		storeLocator.pars.mxlt = Math.max(bounds.getSouthWest().lat(),bounds.getNorthEast().lat())
		storeLocator.pars.mnln = Math.min(bounds.getSouthWest().lng(),bounds.getNorthEast().lng())
		storeLocator.pars.mxln = Math.max(bounds.getSouthWest().lng(),bounds.getNorthEast().lng())
		
		//set cookie
		storeLocator.setCookie()
	},
	
	setCookie: function(){
		//store the new points
		var today = new Date();
		var expire = new Date();
		expire.setTime(today.getTime() + 3600000*2);
		document.cookie = "stLocLat="+escape(storeLocator.pars.lat) + ";expires="+expire.toGMTString();
		document.cookie = "stLocLon="+escape(storeLocator.pars.lon) + ";expires="+expire.toGMTString();
		document.cookie = "stLocZoom="+escape(storeLocator.vars.zoom) + ";expires="+expire.toGMTString();
	
		//go get the stores
		storeLocator.getStores()
	},
	
	getStores: function(){	
		var point = storeLocator.vars.map.getCenter();
		var zoom = storeLocator.vars.map.getZoom();
		if (zoom == 4) return;
		//clear bubble
		storeLocator.map.bubble.hide()
		
		var paraObj = {}
		Object.extend(paraObj,storeLocator.pars)
		
		var pars = Object.toQueryString(paraObj);
		
		//scan cache
		var cached = storeLocator.cache.store.recs.detect(function(v,i){
			if(pars == v.call){
				return v
			}else{
				return false
			}
		});
		
		if(cached){
			storeLocator.showList(cached.response)
		}else{
			storeLocator.locatorService(storeLocator.services.store,pars,storeLocator.showList)
		}
	},
	
	locatorService: function(url,pars,callBack){

		//$('status').innerHTML = encodeURI(pars)
		var myAjax = new Ajax.Request(url, { 
			method: 'get', 
			parameters: encodeURI(pars), 
			onComplete: callBack
		});
	},
	
	showList: function (originalRequest){
		//$('status').innerHTML = $('status').innerHTML +(originalRequest.responseText)
		//is the data from the service or the cache
		if (originalRequest.status == 404 && $('query').value != '' && $('query').value != $('query').getAttribute('title')) {
			storeLocator.degrade = true;
			$('storeSearchForm').submit();
		}
		if(originalRequest.responseText){
			var obj = originalRequest.responseText.evalJSON()
			//load results in cache
			storeLocator.cache.store.recs.unshift({call:this.parameters,response:obj})
			//check size of cache and remove if nessessary
			if(storeLocator.cache.store.recs.length>storeLocator.cache.store.count)
				storeLocator.cache.store.recs.pop()
		}else{
			var obj = originalRequest
		}
		
		//reset current page vars
		storeLocator.resetPage(obj)
		
		//if no stores
		if(obj.COUNT==0){
			storeLocator.msg({dataString:'Sorry, no locations were found in this area'})
			$('ResultHeader').update('<h2 class="welcome">Sorry, no locations were found.</h2>')
			$('ResultList').update('<p>Sorry, no locations were found in this area. <strong style="color:#d81027">Tip: Try zooming out further</strong></p><p>While we have a vast network of stores, no stores were found using your current selection.</p><p><strong>Please refine your search by:</strong><br /><br />- Altering your search parameters<br />- Expanding your zoom level</p>')
			return
		}
		
		//if There are too many stores
		if(obj.COUNT>storeLocator.pars.numResults){
			storeLocator.msg({dataString:'Please Narrow Your Search'})
			$('ResultHeader').update('<h2 class="welcome">Please Narrow Your Search</h2>')
			$('ResultList').update('<p>Please narrow your search.<br /><strong style="color:#d81027">Tip: Try zooming in closer</strong></p><p>With our vast network of stores, the area you have selected includes more than '+ storeLocator.pars.numResults +' stores.</p><p><strong>Please narrow your search by:</strong><br /><br />- Altering your search parameters<br />- Narrowing your zoom level</p>')
			return
		}
		
		//just the right amount of stores
		storeLocator.vars.totalPages = Math.ceil(parseInt(obj.COUNT)/storeLocator.vars.storesPerPage)
	
		//number header
		storeLocator.list.updateStoreNumber(obj)
	
		//record set
		var recSlider = Df.e('div')
		recSlider.id = 'recSlider'
		recSlider.style.top = '0px'
		
		//for each store
		
		obj.RESULTS.each(function(v,i){
			if(v.store){
				//each store
				var rec = Df.e('div')
				rec.id = 'storeList'+i
				rec.className = 'rec'
				if(i==0)rec.className = 'rec first'
				if(i==obj.COUNT-1)rec.className = 'rec last'
				
				//BEGIN map stuff
				//the stores location icon
				var icon = storeLocator.map.icon.MAURC()

				if(v.store.typeID == 'MAURD'){
					icon = storeLocator.map.icon.MAURD()
				}
				else if(v.store.typeID == 'MAURL'){
					icon = storeLocator.map.icon.MAURL()
				}

				//create and add store to map
				var point = new GLatLng(v.store.latitude,v.store.longitude)

				var marker = new GMarker(point,icon)
				//add bubble to marker
				var showBubble = storeLocator.map.bubble.show.curry(i,v,rec.id,marker,false);
				
				storeLocator.vars.map.addOverlay(marker);
				
				//add store to stores array
				storeLocator.vars.stores.push(marker);
					
				//END map stuff
				
				//div for holding store icons
				var storeIcon = Df.e('div').addClassName('storeIcon');

				//store type icon
				if(v.store.typeID == 'MAURSD'){
					storeIcon.e('div').addClassName('iconAffiliate').update()
				}
				else if(v.store.typeID == 'MAURL' || v.store.typeID == 'MAURF' || v.store.typeID == 'MAURC'){
					storeIcon.e('div').addClassName("iconStore").update()
				}

				//append storeIcon to rec
				rec.insert(storeIcon);

				//div for holding store information
				var storeInfo = Df.e('div').addClassName('storeInfo')

				//store Name
				if (v.store.mallPlazaName != null) {
					var a = storeInfo.e('a').addClassName("storeName").update(v.store.locationName + " " + v.store.mallPlazaName)
				}
				else {
					var a = storeInfo.e('a').addClassName("storeName2").update(v.store.locationName)
				}
				//var a = storeInfo.e('div').addClassName("storeName").update(v.store.locationName + "&nbsp;" + v.store.mallPlazaName)
				//map link
				
				a.observe('click', function(e){
					//map link
					//storeLocator.vars.map.setCenter(this.marker.getPoint())
					showBubble();
				}.bind({
					index: i,
					'value': v,
					rec: rec.id,
					marker: marker
				}));

				window.marker = marker;
                
                    GEvent.addListener(marker, "mouseup", showBubble);
                

				storeInfo.e('div').addClassName("address").update(v.store.address1)
				if(v.store.address2){
					storeInfo.e('div').addClassName("address").update(v.store.address2)
				}
				storeInfo.e('div').addClassName("address").update(v.store.city+', '+v.store.stateCode+ ' ' +v.store.postalCode)
				
				//phone number
				if(v.store.phoneNumber){
					storeInfo.e('div').addClassName("phoneNumber").update(storeLocator.val.phone(v.store.phoneNumber))
				}
				//miles
				if(storeLocator.vars.miles){
					storeInfo.e('div').addClassName("miles").update('Approx: ' + v['distance'].round(1) + ' Miles')
				}
				
				//store url
				if(v.store.storeInfoURL){
					storeInfo.e('div').addClassName("storeInfoURL").update('<a href="http://' + v.store.storeInfoURL + '" target="_blank">' + v.store.storeInfoURL + '</a>')
				}
			
				storeInfo.e('div').addClassName("space").update('&nbsp;')

				//driving directions link (in progress)
				if(storeLocator.val.directions(v)){
					var a2 = storeInfo.e('a', 'bottom', {href:storeLocator.val.directions(v), target:"_blank"}).addClassName("drivingDirections").update('Driving Directions')
				}
				
				//store hours link
				var a = storeInfo.e('div').addClassName("storeHours").update('Store Hours')
					
				a.observe('mouseover', function(e){
					e.target.style.color = '#d81027';
				})
				
				a.observe('mouseout', function(e){
					e.target.style.color = '#505050';
				})
				
				//map link
				a.observe('click', function(e){
					//map link
					//storeLocator.vars.map.setCenter(this.marker.getPoint())
					storeLocator.map.bubble.show(this.index,this.value,this.rec,this.marker)
				}.bind({
					index: i,
					'value': v,
					rec: rec.id,
					marker: marker   
				}))
				
				//append storeInfo to rec
				rec.insert(storeInfo);

				//div that clears floats on storeIcon/storeInfo
				var clearIconInfo = Df.e('div').addClassName('clear')

				//append clearIconInfo to rec
				rec.insert(clearIconInfo);

				//add to rec
				recSlider.insert(rec)
			}
		});
	
		$('ResultList').insert(recSlider)
		
		//record navigation
		var nav = Df.e('div').addClassName("nav")

		//back button
		var backBtn = nav.e('div','bottom', {id:'backBtn'}).addClassName("off").update('<< Previous')
		
		backBtn.observe('click', function(e){
			storeLocator.list.pan(storeLocator.vars.currentPageVar - 2)
		})
		
		//next button
		var nextBtn = nav.e('div', 'bottom', {id: 'nextBtn'}).update('Next >>')
		if(obj.COUNT<4){
			nextBtn.className = 'off';
		}
		nextBtn.observe('click', function(e){
			storeLocator.list.pan(storeLocator.vars.currentPageVar)
		});
		
		$('ResultFooter').insert(nav)
		
		//status bar
		var status = Df.e('div').addClassName("status")
		status.appendChild(document.createTextNode('Page '))
		
		//current page
		status.e('span','bottom', {id:"currentPage"}).update(storeLocator.vars.currentPageVar)
		status.appendChild(document.createTextNode(' of '))
		
		//total pages
		status.e('span').addClassName("drivingLink").update(storeLocator.vars.totalPages)
		$('ResultFooter').insert(status)
	}
	
	//END OF MAP UPDATE CASCADE
	
}

storeLocator.map = {
	
	setup:function(map) {
		map = storeLocator.vars.map = new GMap2($(map));
		
		//get rid of bubble shadow
		map.getPane(G_MAP_FLOAT_SHADOW_PANE).style.display = 'none'
		
		if(storeLocator.vars.initialLoad == true){
			storeLocator.map.initialSetup(map);
		}
		else if (location.href.toQueryParams().lat != null && location.href.toQueryParams().lon  != null) {
			storeLocator.map.cachedSetup(map,true,true)
		}
		else
		{
			storeLocator.map.cachedSetup(map,true,false)
		}
	},
	
	initialSetup: function(map){
		//storeLocator.vars.zoom = ;
		
		map.setCenter(new GLatLng(storeLocator.pars.lat, storeLocator.pars.lon), 1);
		if (!storeLocator.vars.storeAvail)
		{
			//$('ResultHeader').update('<h2 class="welcome">Welcome</h2>')
			//$('ResultList').update();//'<p>Welcome to the DC Store Locator. Please enter your location above to find a list of stores in your local area.</p><h2>Using DCs Gift Cards</h2><img src=\"../images/storeLocator_giftCard.gif\" width=\"90\" height=\"56\" border=\"0\" /><p class=\"imgPad\">DCs Gift Cards can only be redeemed online at DCShoes.com, via telephone purchases or in a DC-owned retail store.</p><h2>Returning Online Purchases</h2><p>Online purchases can only be returned or exchanged at a DC-owned retail store or via DCs customer service.</p>';
		}
		
		//storeLocator.map.addMapControls(map)
	},
	
	cachedSetup: function(map,init,pdp) {
		
		if (pdp) {
			map.setCenter(new GLatLng(location.href.toQueryParams().lat, location.href.toQueryParams().lon), storeLocator.vars.zoom);
			storeLocator.getFromHere()
		} else {
			map.setCenter(new GLatLng(storeLocator.pars.lat, storeLocator.pars.lon), storeLocator.vars.zoom);
		}

		storeLocator.map.addMapControls(map);
		
		if(init){
			storeLocator.map.addEvents(map)
			var point = new GLatLng(storeLocator.pars.lat,storeLocator.pars.lon)
			storeLocator.setBounds(point)
		}
		
	},
	
	addMapControls: function(map){
		//get map container
		var obj = map.getContainer()
		if(storeLocator.vars.mapControler){
			obj = $(storeLocator.vars.mapControler)
		}
		
		//add pan control
		//up
		obj.e('div','bottom',{className:'control panUp',
			onmouseover:function(){
			this.style.backgroundPosition = '0pt -27px';
			},
			onmouseout:function(){
			this.style.backgroundPosition = '0pt 0pt';
			},
			onclick:function(){
			map.panDirection(0,+1)
			storeLocator.vars.miles = false
		}});
		//down
		obj.e('div','bottom',{className:'control panDown',
			onmouseover:function(){
			this.style.backgroundPosition = '0pt -27px';
			},
			onmouseout:function(){
			this.style.backgroundPosition = '0pt 0pt';
			},
			onclick:function(){
			map.panDirection(0,-1)
			storeLocator.vars.miles = false
		}});
		//left
		obj.e('div','bottom',{className:'control panLeft',
			onmouseover:function(){
			this.style.backgroundPosition = '0pt -27px';
			},
			onmouseout:function(){
			this.style.backgroundPosition = '0pt 0pt';
			},
			onclick:function(){
			map.panDirection(+1,0)
			storeLocator.vars.miles = false
		}});
		//right
		obj.e('div','bottom',{className:'control panRight',
			onmouseover:function(){
			this.style.backgroundPosition = '0pt -27px';
			},
			onmouseout:function(){
			this.style.backgroundPosition = '0pt 0pt';
			},
			onclick:function(){
			map.panDirection(-1,0)
			storeLocator.vars.miles = false
		}});
		
		//recenter
		var recenter = obj.e('div','bottom',{className:'control recenter',
			onmouseover:function(){
			this.style.backgroundPosition = '0pt -27px';
			},
			onmouseout:function(){
			this.style.backgroundPosition = '0pt 0pt';
			},
			onclick:function(){
			storeLocator.vars.miles = true
			map.returnToSavedPosition()
		}});
		
		//add zoom control
		//in
		obj.e('div','bottom',{id:'zoomIn',className:'control zoomIn',
			onmouseover:function(){
			this.style.backgroundPosition = '0pt -27px';
			},
			onmouseout:function(){
			this.style.backgroundPosition = '0pt 0pt';
			},
			onclick:function(){
			storeLocator.map.zoom(map,+1)
		}});
		//out
		obj.e('div','bottom',{id:'zoomOut',className:'control zoomOut',
			onmouseover:function(){
			this.style.backgroundPosition = '0pt -27px';
			},
			onmouseout:function(){
			this.style.backgroundPosition = '0pt 0pt';
			},
			onclick:function(){
			storeLocator.map.zoom(map,-1)
		}});
		
		//Example of TickSlider use:
		(function () {
			var 
				marker = $$('.storeLocatorMarker')[0],
				params = {
					direction: Df.TickSlider.Horizontal,
					onChange: function (value, index) {
						map.setZoom(value);
					},
					values:[]
				};
			for (i=17; i>=3; i--)
				params.values.push(i);
			
			storeLocator.slider = new Df.TickSlider(marker, params);
			$$('.storeLocatorZoomIncrement').each(function (elem) {
				Element.observe(elem, 'click',function (e) {
					storeLocator.slider.moveIndex(-1);
					storeLocator.slider.update();					
					return Event.stop(e);
				});
			});
			$$('.storeLocatorZoomDecrement').each(function (elem) {
				Element.observe(elem, 'click',function (e) {
					storeLocator.slider.moveIndex(+1);
					storeLocator.slider.update();
					return Event.stop(e);
				});
			});
			$$('input.storeLocatorLeft').each(function (elem) {
				var orig = elem.getAttribute('title');
				Element.observe(elem, 'focus', function (e) {
					if (elem.value==orig) elem.value='';
				});
				Element.observe(elem, 'blur', function (e) {
					if (elem.value=='') elem.value=orig;
				});
				elem.value=orig;
			});
			storeLocator.slider.setCurrentValue(map.getZoom());
			storeLocator.slider.enable();
		})();
		storeLocator.map.adjustZoomButtons(map)
		
		//add map type
		//map
		obj.e('div','bottom',{innerHTML:'Map',id:'cmap',className:'control cmap',
			onmouseover:function(){
				Element.addClassName('cmap', 'cmapHover');
			},
			onmouseout:function(){
				Element.removeClassName('cmap', 'cmapHover');
			},
			onclick:function(){
			storeLocator.map.mapType(map,0)
		}});
		//sat
		obj.e('div','bottom',{innerHTML:'Satellite',id:'csat',className:'control csat',
			onmouseover:function(){
				Element.addClassName('csat', 'csatHover');
			},
			onmouseout:function(){
				Element.removeClassName('csat', 'csatHover');
			},
			onclick:function(){
			storeLocator.map.mapType(map,1)
		}});
		//hybrid
		obj.e('div','bottom',{innerHTML:'Hybrid',id:'chybrid',className:'control chybrid',
			onmouseover:function(){
				Element.addClassName('chybrid', 'cmapHover');
			},
			onmouseout:function(){
				Element.removeClassName('chybrid', 'cmapHover');
			},
			onclick:function(){
			storeLocator.map.mapType(map,2)
		}});
		
		//adjust map type
		storeLocator.map.adjustMapButtons(storeLocator.vars.map)		
	},
	addEvents: function(map){
		GEvent.addListener(map, "dragstart", function() {
			storeLocator.vars.miles = false
		});
		
		GEvent.addListener(map, "moveend", function() {
			storeLocator.getFromHere()
		});
		
		GEvent.addListener(map, "movestart", function() {
			//clear bubble
			storeLocator.map.bubble.hide()
		});
	},
	
	clearMarkers: function(map,stores){
		if(stores.length>0)while(stores.length>0)map.removeOverlay(stores.shift());
	},
	
	zoom: function(map,dir){
		if(dir>0){
			if(storeLocator.vars.maxZoomLevel>(parseInt(map.getZoom())))map.zoomIn()
		}else if(dir<0){
			if(storeLocator.vars.minZoomLevel<(parseInt(map.getZoom())))map.zoomOut()
		}
		storeLocator.map.adjustZoomButtons(map)
	},
	
	adjustZoomButtons: function(map){
		/*
		Element.removeClassName('zoomOut','zoomOutOff')
		Element.removeClassName('zoomIn','zoomInOff')
		if (!!map) storeLocator.vars.zoom = map.getZoom()
		
		if(storeLocator.vars.minZoomLevel>(storeLocator.vars.zoom-1)){
			Element.addClassName('zoomOut','zoomOutOff')
		}
		else if(storeLocator.vars.maxZoomLevel<(storeLocator.vars.zoom+1)){
			Element.addClassName('zoomIn','zoomInOff')
		} 
		if (!!storeLocator.slider) storeLocator.slider.setCurrentValue(storeLocator.map.index(storeLocator.vars.sliderAry,storeLocator.vars.zoom))
		*/
	},
	
	mapType: function(map,i){
		map.setMapType(G_DEFAULT_MAP_TYPES[i])
		storeLocator.map.adjustMapButtons(map)
		
	},
	
	adjustMapButtons: function(map){
		Element.removeClassName('cmap','cmapOn')
		Element.removeClassName('csat','csatOn')
		Element.removeClassName('chybrid','chybridOn')
		
		var type = map.getCurrentMapType().getName()
		if(type == 'Map'){
			Element.addClassName('cmap','cmapOn')
		}else if(type == 'Satellite'){
			Element.addClassName('csat','csatOn')
		}else if(type == 'Hybrid'){
			Element.addClassName('chybrid','chybridOn')
		}
	},
	
	markerToPixel: function(marker){
		var par = false
		loopster:
		for(p in marker){
			try{
				if(marker[p].tagName == 'IMG'){
					par = p
					break loopster
				}
			}catch(e){
				
			}
		}
		if(!par){
			loopster2:
			for(p in marker){
				try{
					if(marker[p].tagName == 'DIV'){
						par = p
						break loopster2
					}
				}catch(e){
					
				}
			}
		}
		if(par){
			var pixels = Position.cumulativeOffset(marker[par])
			var pos = Position.cumulativeOffset($('mainContent').select('.wrap')[0])
			var x = parseInt(pixels[0]) - parseInt(pos[0])
			var y = parseInt(pixels[1]) - parseInt(pos[1])
		}else{
			var x = 0
			var y = 0
		}
		return {x:x,y:y}
	},
	
	index: function(ary,value){
		loopster:
		for(var i=0; i<ary.length; i++){
			if(ary[i] == value){
				return i
				break loopster
			}
		}
		return false	
	}
}

storeLocator.map.icon = {
	MAURD: function(){
		var icon = new GIcon();
		icon.image = "../images/storeLocator/icon_ship.png";
		icon.shadow = "../images/storeLocator/icon_shadow.png";
		icon.iconSize = new GSize(105, 57);
		icon.shadowSize = new GSize(105, 57);
		icon.iconAnchor = new GPoint(44, 55);
		icon.infoWindowAnchor = new GPoint(44, 55);
		return icon
	},
	
	MAURC: function(){
		var icon = new GIcon();
		icon.image = "../images/storeLocator/icon_ship.png";
		icon.shadow = "../images/storeLocator/icon_shadow.png";
		icon.iconSize = new GSize(105, 57);
		icon.shadowSize = new GSize(105, 57);
		icon.iconAnchor = new GPoint(44, 55);
		icon.infoWindowAnchor = new GPoint(44, 55);
		return icon
	},
	MAURL: function(){
		var icon = new GIcon();
		icon.image = "../images/storeLocator/icon_ship.png";
		icon.shadow = "../images/storeLocator/icon_shadow.png";
		icon.iconSize = new GSize(105, 57);
		icon.shadowSize = new GSize(105, 57);
		icon.iconAnchor = new GPoint(44, 55);
		icon.infoWindowAnchor = new GPoint(44, 55);
		return icon
	}
}

storeLocator.map.bubble = {
	
	store: function(i,v){
		var bubble = Df.e('dl').addClassName('mapBubble');
		var contentTab = bubble.e('dt').addClassName('infoTab');
		var content = bubble.e('dd').addClassName("infoContent");
		
		//store Name
		if (v.store.mallPlazaName != null)
			content.e('a').addClassName("storeName").update(v.store.locationName + " " + v.store.mallPlazaName)
		else
			content.e('a').addClassName("storeName2").update(v.store.locationName)
		
		//address
		content.e('div').addClassName("address").update(v.store.address1)
		if(v.store.address2){
			content.e('div').addClassName("address").update(v.store.address2)
		}
		content.e('div').addClassName("address").update(v.store.city+', '+v.store.stateCode+ ' ' +v.store.postalCode)
		
		//phone number
		if(v.store.phoneNumber){
			content.e('div').addClassName("phoneNumber").update(storeLocator.val.phone(v.store.phoneNumber))
		}
		//miles
		if(storeLocator.vars.miles){
			content.e('div').addClassName("miles").update('Approx: ' + v['distance'].round(1) + ' Miles')
		}
		//store url
		if(v.store.storeInfoURL){
			content.e('div').addClassName("storeInfoURL").update('<a href="http://' + v.store.storeInfoURL + '" target="_blank">' + v.store.storeInfoURL + '</a>')
		}
		//directions	
		var a = content.e('a','bottom',{href:storeLocator.val.directions(v), className:"directions", target:"_blank", innerHTML:'Driving Directions'})
		
		//ship to store
		if(v.store.shipToStore == 'Y'){
			content.e('div').addClassName("shipToStore")
		}

		
		if(v.store.storeHours){
			var contentTab = bubble.e('dt').addClassName('hoursTab');
			var content = bubble.e('dd').addClassName("hoursContent");
			//store hours
			content.e('div').addClassName("hoursTitle").update('Store Hours')
			if (v.store.hours.openingTimeMon > 0 && v.store.hours.openingTimeTue > 0 && v.store.hours.openingTimeWed > 0 && v.store.hours.openingTimeThu > 0 && v.store.hours.openingTimeFri > 0 && v.store.hours.openingTimeSat > 0)
			{
				if (v.store.hours.closingTimeMon == 0){ v.store.hours.closingTimeMon = 2400; }
				if (v.store.hours.closingTimeTue == 0){ v.store.hours.closingTimeTue = 2400; }
				if (v.store.hours.closingTimeWed == 0){ v.store.hours.closingTimeWed = 2400; }
				if (v.store.hours.closingTimeThu == 0){ v.store.hours.closingTimeThu = 2400; }
				if (v.store.hours.closingTimeFri == 0){ v.store.hours.closingTimeFri = 2400; }
				if (v.store.hours.closingTimeSat == 0){ v.store.hours.closingTimeSat = 2400; }
				if (v.store.hours.openingTimeSun && v.store.hours.closingTimeSun == 0){ v.store.hours.closingTimeSun = 2400; }
				
				var tblHours = '<table cellpadding="0" cellspacing="0" border="0" width="92%">' +
				'<tr><td>Mon</td>' + storeLocator.val.hours(v.store.hours.openingTimeMon, v.store.hours.closingTimeMon) +
				'<tr><td>Tue</td>' + storeLocator.val.hours(v.store.hours.openingTimeTue, v.store.hours.closingTimeTue) +
				'<tr><td>Wed</td>' + storeLocator.val.hours(v.store.hours.openingTimeWed, v.store.hours.closingTimeWed) +
				'<tr><td>Thu</td>' + storeLocator.val.hours(v.store.hours.openingTimeThu, v.store.hours.closingTimeThu) +
				'<tr><td>Fri</td>' + storeLocator.val.hours(v.store.hours.openingTimeFri, v.store.hours.closingTimeFri) +
				'<tr><td>Sat</td>' + storeLocator.val.hours(v.store.hours.openingTimeSat, v.store.hours.closingTimeSat) +
				'<tr><td>Sun</td>' + storeLocator.val.hours(v.store.hours.openingTimeSun, v.store.hours.closingTimeSun) + '</tr></table>'
				content.e('div').addClassName("storeHours").update(tblHours)
			} else {
				content.e('div').addClassName("storeHours").update(v.store.storeHours)
			}
		}
		
		//close btn
		var closeIt = Df.e('div').addClassName("closeIt")
		closeIt.observe('click', function(e){
			storeLocator.map.bubble.hide()
			storeLocator.list.goDim()
		})
		
		bubble.insert(closeIt)
		
		var mapBubbleContainer = Df.e('div').addClassName('mapBubbleContainer')
		mapBubbleContainer.page = Math.floor($$('#recSlider .rec')[i].offsetTop / $('ResultList').offsetHeight);
		mapBubbleContainer.insert(bubble)
		
		setTimeout(function(){
			$$('dl.mapBubble dd').each(function(elem){
				elem.setStyle({opacity: 0});
			});		
			var para = {animate: {time:200, opacity:1}};
			try {
				var tab1 = $$('dl.mapBubble')[0].tabset(para);
				tab1.showItem(0);
				//!!! probably for the worst, but I need to do this quick.
				var mapBubble = $$('dl.mapBubble')[0];
				mapBubble.select('dt').each(function (elem) {
					elem.observe('click', function () {
						mapBubble.className = 'mapBubble';
						mapBubble.addClassName(elem.className.toString().replace(/ *active[^ ]* */,'')+'_bubble');
					});
				});
			} catch (e) {}
		}, 1);


		return mapBubbleContainer;
	},
	
	hide: function(){
		var bubbles = $$('.mapBubbleContainer')
		for(var i=0; i<bubbles.length; i++){
			bubbles[i].remove()
		}
	},
	
	show: function(i,v,rec,marker,pan){
		//hide Bubbles
		storeLocator.map.bubble.hide();
		
		function getOffset(el, dim) {
			if (typeof stop == 'undefined')
				stop = document.body;
			dim = 'offset'+dim.substr(0,1).toUpperCase()+dim.substr(1).toLowerCase();
			var ret = 0;
			
			do {
				//WHAT THE HELL IS /WRONG/ WITH IE6?
				if (el.id == 'map' && dim=='offsetLeft')
					ret-=10263;
				if (el.id == 'map' && dim=='offsetTop')
					ret-=345;
				ret+=parseInt(el[dim]);
			}  while (document.body !== (el = el.getOffsetParent()));
			return ret;
		}
		//IE8 hack; DOM doesn't update with enough quickness.
		setTimeout(function () {
			
			//get pixels
			var pixels = storeLocator.map.markerToPixel(marker)
			
			//center map
			//storeLocator.vars.map.setCenter(marker.getPoint())
			var left = pixels.x - 148;
			var top = pixels.y - 147;
			if(Prototype.Browser.IE){
				left = pixels.x - 159;
				top = pixels.y - 147;
				var img = GMap.imgName(marker);
				if (Prototype.Browser.ie6) {
					var reference = $('mainContent').select('.wrap');
					left = getOffset(marker[img], 'left');
					top = getOffset(marker[img], 'top');
				}
			}	
			
			//show bubble
			var bubble = storeLocator.map.bubble.store(i,v)
			bubble.style.left = left + 'px'
			bubble.style.top = top + 'px'
			$('mainContent').select('.wrap')[0].insert(bubble)		
			
			if(pan){
				storeLocator.list.pan(bubble.page)
			}
			
			storeLocator.list.hightLight(rec)
		},1);
	}
}

storeLocator.list = {
	pan: function(page){
		var top = page*(storeLocator.vars.storeHeight*-storeLocator.vars.storesPerPage)
		var elm = $('recSlider')
		var current = parseInt(elm.style.top)
		var skip = parseInt(Math.abs(top-current)/(storeLocator.vars.storeHeight*storeLocator.vars.storesPerPage))
		var update = false

		if(top>current){
			if(page>=0){
				$('recSlider').animate({top: top})
				update = true
			}else{
				$('backBtn').className = 'off'
			}
		}else if(top<current){
			if(page<storeLocator.vars.totalPages){
				$('recSlider').animate({top: top})
				update = true
			}
		}
		if(update){
			storeLocator.vars.currentPageVar = page + 1
			$('currentPage').update(storeLocator.vars.currentPageVar)
			$('nextBtn').className = ''
			$('backBtn').className = ''
			if(storeLocator.vars.currentPageVar==storeLocator.vars.totalPages){
				$('nextBtn').className = 'off'
			}
			else if(storeLocator.vars.currentPageVar==1){
				$('backBtn').className = 'off'
			}
		}
	},
	
	hightLight: function(obj){
		storeLocator.list.goDim()
		$(obj).addClassName('on')
	},
	
	goDim: function(){
		var ary = $$('#ResultList .rec')
		ary.each(function(v,i){
			Element.removeClassName(v,'on')
		});
	},
	
	updateStoreNumber: function(obj){
		var count = document.createElement('div')
		var html = '<div class="fB">There is 1 store in your area</div>'
		if(obj.COUNT > 1){
			html = '<div class="fB">There are ' + obj.COUNT + ' stores in your area</div>'
		}
		if ($('ResultCMS')) {$('ResultCMS').hide()}
		$('ResultHeader').update(html)
	}
}

storeLocator.val = {
		toStdTime: function(myTime){
		var i = parseInt(myTime)
		if(i == 0 || i == 2400){
			return '12:00 AM'
		}else if(i==1200){
			return '12:00 PM'
		}else{
			if(i<1200){
				var str = String(i)
				var end = "AM"
			}else{
				var str = String(i-1200)
				var end = "PM"
			}
			return str.substring(0,(str.length-2))+':'+str.substr((str.length-2),2)+ ' ' + end
		}
	},

	hours: function(start,end){
		if(start && end){ 
			return '<td align="right">' + storeLocator.val.toStdTime(start) + ' to ' + storeLocator.val.toStdTime(end) + '</td>'
		}else{
			return '<td align="right">CLOSED</td>'
		}	
	},
	
	phone: function(string){
		string = string.replace(/-/g,'')
		if(string && string.length == 10){
			return '<span>Tel: </span>('+string.substring(0,3)+') '+string.substring(3,6)+'-'+string.substring(6,10)
		}else{
			return '<span>Tel: </span>'+string
		}
	},
	
	directions: function(v){
		if(storeLocator.vars.address != " "){	
			return 'http://maps.google.com/maps?saddr='+storeLocator.pars.lat+','+storeLocator.pars.lon+'('+encodeURI(storeLocator.vars.address)+')&daddr='+v.store.latitude+','+v.store.longitude+'('+encodeURI(v.store.address1+' '+v.store.city+', '+v.store.stateCode+' '+v.store.postalCode)+')';
		}else{
			return 'http://maps.google.com/maps?q='+v.store.latitude+','+v.store.longitude+'('+encodeURI(v.store.address1+' '+v.store.city+', '+v.store.stateCode+' '+v.store.postalCode)+')';
		}
	}
}