/*
 * FormExtensions.js
 *
 */

// automatically execute several common features, but not all features in this file

window.addEvent('domready', windowStartupBunchaStuff);


// sets a bunch of auto-configured objects
var MyCdVehicles, MyCdVehicleListings;
function windowStartupBunchaStuff( ) {
	if (MyCdVehicleListings) { // prevent double-execution
		return;
	}
	
	MyCdVehicleListings = new CdVehicleListings();
	if (MyCdVehicleListings.listings === undefined) {
		MyCdVehicles = new CdVehicles(document);
	}
	
	emptyOverlay();
	
//	numberUpDownFieldSetter();
	JSFV.setter();
//	autoSuggesterInit();
	
//	floatersInit();
	CdFloaters.prototype.makeClickable();
	setKeepTop();
	
//	var floaters = new CdFloaters;
//	floaters.init();
	
	initCalendar();
	
	initIE6Hover();
}

/*
 * Auto-Suggest Vehicle Make/Model. Used by CdVehicle() to attach suggesters.
 * 
 * @usage: vehicleAutoSuggest('makeFieldId', 'modelFieldId', 'nextInputFieldId');
 * 
 */
function vehicleAutoSuggest( make, model, next ) {
	new vehicleAutoSuggester(make, this.makes, model, 0, '');
	new vehicleAutoSuggester(model, this.make_models, next, this.models_only, make);
}


/*
 * Auto-Suggest Vehicle Make/Model
 * vehicleAutoSuggester(input, m_array, next_div, s_array, prev_div)
 * 	input: "this" input field
 *  m_array: make/model array
 *  next_div: element you want to have focus after successful selection
 *  s_array: models array
 *  prev_div: "make" field when filling "model"
 * 
 * Implementation requires two setters: make and model
 * @usage: new vehicleAutoSuggester('makeFieldId', makes, 'modelFieldId', 0, '');
 * @usage: new vehicleAutoSuggester('modelFieldId', make_models, 'nextInputFieldId', models_only, 'nextInputFieldId', 'makeFieldId');
 */
function vehicleAutoSuggester( input, m_array, next_div, s_array, prev_div ) {
	this.input = $(input);
	if (!this.input) {
		return;
	}
	
	this.suggester = null;
	this.scroller = null;
	this.empty = true;
	this.highlighted = null;
	
	this.makeModels = m_array;
	this.m_array = m_array;
	this.s_array = s_array;
	this.next_div = next_div;
	this.prev_div = prev_div;
	
	this.clickedDiv = false;
	
	this.input.addEvents({
		// on blur from field, close suggestion box but allow suggestion to be clicked
		'blur': (function( e ) {
			if (this.clickedDiv) {
				e.stop();
				this.input.focus(); // for IE7, prevent click on scrollbar from bluring input field
				return;
			}
			
			(function( ){
				this.dispose();
			}).bind(this).delay(250); // after delay, drop the suggestion div
		}).bindWithEvent(this),
		'keypress': (function( e ) {
			switch(e.event.keyCode) {
				case 13: // RETURN
					e.stop();
					break;
				case 9: // TAB
					this.dispose();
					break;
				default:
					break;
			}
		}).bindWithEvent(this),
		'keyup': (function( e ) {
			switch (e.event.keyCode) {
				case 9:  // tab
				case 16: // shift
				case 17: // ctrl
				case 18: // alt
				case 20: // caps lock
				case 91: // window key
					break;	// ignore these keys -- avoid unnecessary rebuilding
				case 38: // UP KEY
					this.highlightPrevious();
					break;
				case 40: // DOWN KEY
					this.highlightNext();
					break;
				case 27: // ESCAPE KEY
					this.dispose();
					break;
				case 13: // RETURN KEY
					this.useHighlighted();
					break;
				default:
					this.buildSuggestions();
					break;
			} // switch
		}).bindWithEvent(this), // keyup
		'focus': (function( e ) {
			if (this.clickedDiv) {
				this.clickedDiv = false; // for IE7, prevent click on scrollbar from rebuilding suggestions
				e.stop();
				return;
			}
			this.buildSuggestions();
		}).bindWithEvent(this)
	}); // addEvents()
}

vehicleAutoSuggester.prototype.dispose = function( ) {
	if (this.suggester) {
		this.suggester.dispose();
		this.suggester = null;
		this.empty = true;
	}
};

vehicleAutoSuggester.prototype.useHighlighted = function( ) {
	if (this.highlighted) {
		this.input.value = this.highlighted.innerHTML;
	}
	$(this.next_div).focus();
	this.dispose();
};

vehicleAutoSuggester.prototype.highlight = function( div ) {
	if (div) {
		if (this.highlighted) {
			this.highlighted.removeClass('highlighted_row');
		}
		this.highlighted = div;
		this.highlighted.addClass('highlighted_row');
		this.scroller.toElement(this.highlighted);
	}
};

vehicleAutoSuggester.prototype.highlightNext = function( ) {
	if (this.suggester && !this.empty) {
		if (!this.highlighted) {
			this.highlight(this.suggester.getFirst());
		} else {
			this.highlight(this.highlighted.getNext());
		}
	}
};

vehicleAutoSuggester.prototype.highlightPrevious = function( ) {
	if (this.suggester) {
		if (!this.highlighted) {
			this.highlight(this.suggester.getFirst());
		} else {
			this.highlight(this.highlighted.getPrevious());
		}
	}
};

vehicleAutoSuggester.prototype.buildSuggestions = function( ) {
	var val = this.input.value.toLowerCase();
	var len = val.length;
	var results_name = new Array();
	var x;
	
	if (this.s_array !== 0) {  // update arrays if we have a dependant array
		prev_value = this.prev_div.value;
		this.m_array = this.makeModels[prev_value];
		if (typeof(this.m_array) == 'undefined') {
			this.m_array = this.s_array;
		}
	}
	
	if (len > 0) {
		for (x = 0; x < this.m_array.length; x++) {
			if (this.m_array[x].substring(0,len).toLowerCase() == val) {
				results_name.push(this.m_array[x]);		// track results
			}
		}
	}
	
	// populate box, display div, highlight first row
	this.highlighted = null;
	var prev_value = '';
	if (results_name.length === 0) {
		this.dispose();
		return;
	}
	
	if (!this.suggester) { // create a box for this if this is the first time
		this.suggester = new Element('div', {
			'class': 'AutoSuggestResults',
			'events': {
				'mousedown': (function( e ) { // for IE7, prevent click on scrollbar from bluring input field
					if (Browser.Engine.trident) {
						this.clickedDiv = true;
						e.stop();
					}
				}).bindWithEvent(this)
			}
		});
		this.suggester.inject(this.input, 'after');
		
		this.scroller = new Fx.Scroll2(this.suggester, { duration: 100 });
	} else {
		this.suggester.getChildren().each(function( div ) { div.dispose(); });
	}
	
	var inside = '';
	if (results_name.length) {
		this.empty = false;
		for (x = 0; x < results_name.length; x++) {
			inside += '<div style="cursor: pointer;">' + results_name[x] + '</div>';
		}
	} else {
		this.empty = true;
	}
	
	var dim = this.input.getCoordinates();
	this.suggester.innerHTML = inside;
	this.suggester.setStyles({
		'width': (dim.width - 5) + 'px',
		'left': (dim['left'] - 15) + 'px',
		'top': (dim['top'] + dim['height'] + 4) + 'px',
		'height': '60px',
		'overflow': 'auto'
	});
	
	// add click events
	var _this = this;
	this.suggester.getChildren().each(function( div ) {
		div.addEvent('click', (function( e, div ) {
			this.highlight(div);
			this.useHighlighted();
		}).bindWithEvent(_this, div));
	});
	
	this.highlightNext();
};



/**
**** THIS CREATES A TOO-LARGE make_model LIST. GOING WITH JASON'S ORIGINAL LIST BELOW. ****
# to create the text that goes below

cat >vehicleMakeModels.sql

SET @@group_concat_max_len = 64000; # make sure we can hold data -- max as of 04/09/08 is 49,779


SELECT "vehicleAutoSuggest.prototype.makes =  [" ``;

SELECT GROUP_CONCAT(DISTINCT CONCAT('"', REPLACE(short_make, '/', '\\/'), '"') ORDER BY short_make SEPARATOR ',') ``
FROM trucking.vehicle_specs;

SELECT "];" ``;
SELECT "" ``;


SELECT "vehicleAutoSuggest.prototype.make_models =  {" ``;

SELECT CONCAT('"', REPLACE(short_make, '/', '\\/'), '": [', GROUP_CONCAT(DISTINCT CONCAT('"', REPLACE(short_model, '/', '\\/'), '"') ORDER BY short_model SEPARATOR ','), '],') ``
FROM trucking.vehicle_specs
#WHERE short_make like 'm%'
GROUP BY short_make
ORDER BY short_make;

SELECT "};" ``;
SELECT "" ``;


SET @@group_concat_max_len = 354000; # make sure we can hold data -- total as of 04/09/08 is 108,691

SELECT "vehicleAutoSuggest.prototype.models_only = [" ``;

SELECT GROUP_CONCAT(DISTINCT CONCAT('"', REPLACE(short_model, '/', '\\/'), '"') ORDER BY short_model SEPARATOR ',') ``
FROM trucking.vehicle_specs;

SELECT "];" ``;

SET @@group_concat_max_len = 1024;

#eof

mysql -P3308 -uroot -pbdfw65 <vehicleMakeModels.sql >vehicleMakeModels.js



ll vehicleMakeModels.js

 */

vehicleAutoSuggest.prototype.make_models =  {
"Acura":["CL","Integra","Legend","MDX","RDX","RL","RSX","SLX","TL","TSX","Vigor"],"Aston Martin":["DB7","DB9","DBS","V12 Vanquish","V8 Vantage"],"Audi":["100","200","80","90","A3","A4","A5","A6","A7","A8","allroad quattro","Cabriolet","Coupe","Q5","Q7","R8","R8-RS","RS4","RS5","RS6","S4","S5","S6","S8","TT","TT-RS","TTS","V8"],"Bentley":["Arnage","Azure","Brooklands","Continental","Continental Flying Spur","Continental GT","Continental GT Speed","Continental GTC"],"BMW":["1 Series","128i","135i","3 Series","328i","335i","5 Series","528i","535i","550i","6 Series","650i","7 Series","750i","750Li","760Li","ALPINA B7","M3","M6","X3","X5","X6","Z3","Z4","Z8"],"Bugatti":["Veyron"],"Buick":["Century","Electra","Enclave","Estate Wagon","LaCrosse","LeSabre","Lucerne","Park Avenue","Rainier","Reatta","Regal","Rendezvous","Riviera","Roadmaster","Skylark","Terraza"],"Cadillac":["Allante","Brougham","Catera","CTS","CTS-V","DeVille","DTS","Eldorado","Escalade","Escalade ESV","Escalade EXT","Escalade Hybrid","Fleetwood","Seville","Sixty Special","SRX","STS","STS-V","XLR","XLR-V"],"Chevrolet":["Astro","Astro Cargo","Avalanche","Aveo","Beretta","Blazer","CK 1500 Series","C\/K 2500 Series","C\/K 3500 Series","Caprice","Cavalier","Celebrity","Chevy Van","Chevy Van Classic","Classic","Cobalt","Colorado","Corsica","Corvette","Equinox","Express","Express Cargo","HHR","Impala","Lumina","Lumina Minivan","Malibu","Malibu Classic","Malibu Hybrid","Malibu Maxx","Metro","Monte Carlo","Prizm","R\/V 3500 Series","S-10","S-10 Blazer","Silverado 1500","Silverado 1500 Classic","Silverado 1500 SS","Silverado 1500 SS Classic","Silverado 1500HD","Silverado 1500HD Classic","Silverado 2500","Silverado 2500HD","Silverado 2500HD Classic","Silverado 3500","Silverado 3500 Classic","Silverado 3500HD","Sportvan","SSR","Suburban","Tahoe","Tahoe Hybrid","Tahoe Limited\/Z71","Tracker","TrailBlazer","TrailBlazer EXT","Traverse","Uplander","Venture"],"Chrysler":["300","300C SRT-8","300M","Aspen","Cirrus","Concorde","Crossfire","Crossfire SRT-6","Grand Voyager","Imperial","Le Baron","LHS","New Yorker","Pacifica","Prowler","PT Cruiser","Sebring","TC","Town and Country","Voyager"],"Dodge":["Avenger","Caliber","Caravan","Challenger","Charger","Charger SRT-8","Colt","Dakota","Daytona","Durango","Dynasty","Grand Caravan","Intrepid","Journey","Magnum","Magnum SRT-8","Monaco","Neon","Neon SRT-4","Nitro","Omni","RAM 150","RAM 250","RAM 350","Ram 50 Pickup","Ram Cargo","Ram Pickup 1500","Ram Pickup 1500 SRT-10","Ram Pickup 2500","Ram Pickup 3500","Ram Van","Ram Wagon","Ramcharger","Shadow","Spirit","Sprinter","Sprinter Cargo","Stealth","Stratus","Viper"],"Ferrari":["360","430 Scuderia","456M","550","575M","599","612 Scaglietti","Enzo","F430","Superamerica"],"Ford":["Aerostar","Aspire","Bronco","Bronco II","Contour","Contour SVT","Crown Victoria","E-150","E-250","E-350","Econoline Cargo","Econoline Wagon","Edge","Escape","Escape Hybrid","Escort","Excursion","Expedition","Expedition EL","Explorer","Explorer Sport","Explorer Sport Trac","F-150","F-150 Heritage","F-150 SVT Lightning","F-250","F-250 Super Duty","F-350","F-350 Super Duty","F-450 Super Duty","Festiva","Five Hundred","Flex","Focus","Focus SVT","Freestar","Freestyle","Fusion","GT","LTD Crown Victoria","Mustang","Mustang SVT Cobra","Probe","Ranger","Shelby GT500","Taurus","Taurus X","Tempo","Thunderbird","Windstar","Windstar Cargo"],"GMC":["Acadia","C\/K 2500 Series","C\/K 3500 Series","Canyon","Envoy","Envoy XL","Envoy XUV","Jimmy","R\/V 3500 Series","Rally Wagon","S-15","S-15 Jimmy","Safari","Safari Cargo","Savana","Savana Cargo","Sierra 1500","Sierra 1500 Classic","Sierra 1500HD","Sierra 1500HD Classic","Sierra 2500","Sierra 2500HD","Sierra 2500HD Classic","Sierra 3500","Sierra 3500 Classic","Sierra 3500HD","Sierra C3","Sierra Classic 1500","Sierra Classic 2500","Sierra Classic 3500","Sonoma","Suburban","Syclone","Typhoon","Vandura","Yukon","Yukon Denali","Yukon Hybrid","Yukon XL"],"Honda":["Accord","Civic","Civic CRX","Civic del Sol","CR-V","Element","Fit","Insight","Odyssey","Passport","Pilot","Prelude","Ridgeline","S2000"],"HUMMER":["H1","H1 Alpha","H2","H2 SUT","H3","H3T"],"Hyundai":["Accent","Azera","Elantra","Entourage","Excel","Genesis","Santa Fe","Scoupe","Sonata","Tiburon","Tucson","Veracruz","XG300","XG350"],"Infiniti":["EX35","FX35","FX45","FX50","G20","G35","G37","I30","I35","J30","M30","M35","M45","Q45","QX4","QX56"],"Isuzu":["Amigo","Ascender","Axiom","Hombre","i-Series","Impulse","Oasis","Pickup","Rodeo","Rodeo Sport","Stylus","Trooper","VehiCROSS"],"Jaguar":["S-Type","S-Type R","X-Type","XF","XJ-Series","XJR","XK-Series","XKR"],"Jeep":["Cherokee","Comanche","Commander","Compass","Grand Cherokee","Grand Cherokee SRT-8","Grand Wagoneer","Liberty","Patriot","Wagoneer","Wrangler"],"Kia":["Amanti","Borrego","Optima","Rio","Rondo","Sedona","Sephia","Sorento","Spectra","Sportage"],"Lamborghini":["Diablo","Gallardo","Murcielago"],"Land Rover":["Defender","Discovery","Discovery Series II","Freelander","LR2","LR3","Range Rover","Range Rover Sport"],"Lexus":["ES 250","ES 300","ES 330","ES 350","GS 300","GS 350","GS 400","GS 430","GS 450h","GS 460","GX 470","IS 250","IS 300","IS 350","IS F","LS 400","LS 430","LS 460","LS 600h L","LX 450","LX 470","LX 570","RX 300","RX 330","RX 350","RX 400h","SC 300","SC 400","SC 430"],"Lincoln":["Aviator","Blackwood","Continental","LS","Mark LT","Mark VII","Mark VIII","MKS","MKX","MKZ","Navigator","Navigator L","Town Car","Zephyr"],"Lotus":["Eagle","Elise","Esprit","Exige"],"Maserati":["Coupe","GranSport","GranTurismo","Quattroporte"],"Maybach":["57","62"],"Mazda":["323","626","929","B-Series","B-Series Pickup","B-Series Truck","CX-7","CX-9","MAZDA3","MAZDA5","MAZDA6","MAZDASPEED MAZDA3","MAZDASPEED MAZDA6","MAZDASPEED MX-5 Miata","Mazdaspeed Protege","Millenia","MPV","MX-3","MX-5 Miata","MX-6","Navajo","Protege","Protege5","RX-7","RX-8","Tribute","Tribute Hybrid","Truck"],"Mercedes-Benz":["190-Class","300-Class","350-Class","400-Class","420-Class","500-Class","560-Class","600-Class","C-Class","C32 AMG","C36 AMG","C43 AMG","C55 AMG","CL-Class","CL55 AMG","CL65 AMG","CLK-Class","CLK55 AMG","CLS-Class","CLS55 AMG","E-Class","E55 AMG","G-Class","G55 AMG","GL-Class","M-Class","ML55 AMG","R-Class","S-Class","S55 AMG","S65 AMG","SL-Class","SL55 AMG","SL65 AMG","SLK-Class","SLK32 AMG","SLK55 AMG","SLR McLaren"],"Mercury":["Capri","Cougar","Grand Marquis","Marauder","Mariner","Mariner Hybrid","Milan","Montego","Monterey","Mountaineer","Mystique","Sable","Topaz","Tracer","Villager"],"MINI":["Cooper","Cooper Clubman","Crossman"],"Mitsubishi":["3000GT","Diamante","Eclipse","Eclipse Spyder","Endeavor","Expo","Galant","Lancer","Lancer Evolution","Mighty Max Pickup","Mirage","Montero","Montero Sport","Outlander","Precis","Raider","Sigma","Vanwagon"],"Nissan":["200SX","240SX","300ZX","350Z","Altima","Altima Hybrid","Armada","Axxess","Frontier","GT-R","Maxima","Murano","NX","Pathfinder","Pulsar","Quest","Rogue","Sentra","Stanza","Titan","Truck","Van","Versa","Xterra"],"Pontiac":["6000","Aztek","Bonneville","Firebird","G5","G6","G8","Grand Am","Grand Prix","GTO","Le Mans","Montana","Montana SV6","Solstice","Sunbird","Sunfire","Torrent","Trans Sport","Vibe"],"Porsche":["911","928","944","968","Boxster","Carrera GT","Cayenne","Cayman","Cayman S"],"Rolls-Royce":["Corniche","Park Ward","Phantom","Phantom Drophead Coupe","Silver Seraph"],"Saab":["3-Sep","5-Sep","9-2X","9-7X","900","9000"],"Saturn":["Astra","Aura","Aura Hybrid","ION","ION Red Line","L-Series","L300","Outlook","Relay","S-Series","Sky","VUE","VUE Hybrid"],"Scion":["tC","xA","xB","xD"],"smart":["fortwo"],"Subaru":["B9 Tribeca","Baja","Forester","Impreza","Impreza WRX STi","Justy","Legacy","Loyale","Outback","SVX","Tribeca","XT"],"Suzuki":["Aerio","Esteem","Forenza","Grand Vitara","Reno","Samurai","Sidekick","SX4","Verona","Vitara","X-90","XL7"],"Tesla":["Roadster"],"Toyota":["4Runner","Avalon","Camry","Camry Hybrid","Camry Solara","Celica","Corolla","Cressida","ECHO","FJ Cruiser","Highlander","Highlander Hybrid","Land Cruiser","Matrix","MR2","MR2 Spyder","Paseo","Pickup","Previa","Prius","RAV4","Sequoia","Sienna","Supra","T100","Tacoma","Tercel","Tundra","Yaris"],"Volkswagen":["Cabrio","Cabriolet","Corrado","Eos","EuroVan","Fox","GLI","Golf","GTI","Jetta","New Beetle","Passat","Phaeton","R32","Rabbit","Routan","Tiguan","Touareg","Touareg 2","Vanagon"],"Volvo":["240","740","760","780","850","940","960","C30","C70","Coupe","S40","S60","S60 R","S70","S80","S90","V40","V50","V70","V70 R","V90","XC","XC70","XC90"]
};

vehicleAutoSuggest.prototype.makes = ["Acura","Aston Martin","Audi","Bentley","BMW","Bugatti","Buick","Cadillac","Chevrolet","Chrysler","Dodge","Ferrari","Ford","GMC","Honda","HUMMER","Hyundai","Infiniti","Isuzu","Jaguar","Jeep","Kia","Lamborghini","Land Rover","Lexus","Lincoln","Lotus","Maserati","Maybach","Mazda","Mercedes-Benz","Mercury","MINI","Mitsubishi","Nissan","Pontiac","Porsche","Rolls-Royce","Saab","Saturn","Scion","smart","Subaru","Suzuki","Tesla","Toyota","Volkswagen","Volvo"];

vehicleAutoSuggest.prototype.models_only = ["1 Series","3 Series","3-Sep","4Runner","5 Series","5-Sep","6 Series","7 Series","9-2X","9-7X","57","62","80","90","100","128i","135i","190-Class","200","200SX","240","240SX","300","300-Class","300C SRT-8","300M","300ZX","323","328i","335i","350-Class","350Z","360","400-Class","420-Class","430 Scuderia","456M","500-Class","528i","535i","550","550i","560-Class","575M","599","600-Class","612 Scaglietti","626","650i","740","750i","750Li","760","760Li","780","850","900","911","928","929","940","944","960","968","3000GT","6000","9000","A3","A4","A5","A6","A7","A8","Acadia","Accent","Accord","Aerio","Aerostar","Allante","allroad quattro","ALPINA B7","Altima","Altima Hybrid","Amanti","Amigo","Armada","Arnage","Ascender","Aspen","Aspire","Astra","Astro","Astro Cargo","Aura","Aura Hybrid","Avalanche","Avalon","Avenger","Aveo","Aviator","Axiom","Axxess","Azera","Aztek","Azure","B-Series","B-Series Pickup","B-Series Truck","B9 Tribeca","Baja","Beretta","Blackwood","Blazer","Bonneville","Borrego","Boxster","Bronco","Bronco II","Brooklands","Brougham","C-Class","C\/K 1500 Series","C\/K 2500 Series","C\/K 3500 Series","C30","C32 AMG","C36 AMG","C43 AMG","C55 AMG","C70","Cabrio","Cabriolet","Caliber","Camry","Camry Hybrid","Camry Solara","Canyon","Capri","Caprice","Caravan","Carrera GT","Catera","Cavalier","Cayenne","Cayman","Cayman S","Celebrity","Celica","Century","Challenger","Charger","Charger SRT-8","Cherokee","Chevy Van","Chevy Van Classic","Cirrus","Civic","Civic CRX","Civic del Sol","CL","CL-Class","CL55 AMG","CL65 AMG","Classic","CLK-Class","CLK55 AMG","CLS-Class","CLS55 AMG","Cobalt","Colorado","Colt","Comanche","Commander","Compass","Concorde","Continental","Continental Flying Spur","Continental GT","Continental GTC","Continental GT Speed","Contour","Contour SVT","Cooper","Cooper Clubman","Corniche","Corolla","Corrado","Corsica","Corvette","Cougar","Coupe","CR-V","Cressida","Crossfire","Crossfire SRT-6","Crossman","Crown Victoria","CTS","CTS-V","CX-7","CX-9","Dakota","Daytona","DB7","DB9","DBS","Defender","DeVille","Diablo","Diamante","Discovery","Discovery Series II","DTS","Durango","Dynasty","E-150","E-250","E-350","E-Class","E55 AMG","Eagle","ECHO","Eclipse","Eclipse Spyder","Econoline Cargo","Econoline Wagon","Edge","Elantra","Eldorado","Electra","Element","Elise","Enclave","Endeavor","Entourage","Envoy","Envoy XL","Envoy XUV","Enzo","Eos","Equinox","ES 250","ES 300","ES 330","ES 350","Escalade","Escalade ESV","Escalade EXT","Escalade Hybrid","Escape","Escape Hybrid","Escort","Esprit","Estate Wagon","Esteem","EuroVan","EX35","Excel","Excursion","Exige","Expedition","Expedition EL","Explorer","Explorer Sport","Explorer Sport Trac","Expo","Express","Express Cargo","F-150","F-150 Heritage","F-150 SVT Lightning","F-250","F-250 Super Duty","F-350","F-350 Super Duty","F-450 Super Duty","F430","Festiva","Firebird","Fit","Five Hundred","FJ Cruiser","Fleetwood","Flex","Focus","Focus SVT","Forenza","Forester","fortwo","Fox","Freelander","Freestar","Freestyle","Frontier","Fusion","FX35","FX45","FX50","G-Class","G5","G6","G8","G20","G35","G37","G55 AMG","Galant","Gallardo","Genesis","GL-Class","GLI","Golf","Grand Am","Grand Caravan","Grand Cherokee","Grand Cherokee SRT-8","Grand Marquis","Grand Prix","Grand Vitara","Grand Voyager","Grand Wagoneer","GranSport","GranTurismo","GS 300","GS 350","GS 400","GS 430","GS 450h","GS 460","GT","GT-R","GTI","GTO","GX 470","H1","H1 Alpha","H2","H2 SUT","H3","H3T","HHR","Highlander","Highlander Hybrid","Hombre","i-Series","I30","I35","Impala","Imperial","Impreza","Impreza WRX STi","Impulse","Insight","Integra","Intrepid","ION","ION Red Line","IS 250","IS 300","IS 350","IS F","J30","Jetta","Jimmy","Journey","Justy","L-Series","L300","LaCrosse","Lancer","Lancer Evolution","Land Cruiser","Le Baron","Legacy","Legend","Le Mans","LeSabre","LHS","Liberty","Loyale","LR2","LR3","LS","LS 400","LS 430","LS 460","LS 600h L","LTD Crown Victoria","Lucerne","Lumina","Lumina Minivan","LX 450","LX 470","LX 570","M-Class","M3","M6","M30","M35","M45","Magnum","Magnum SRT-8","Malibu","Malibu Classic","Malibu Hybrid","Malibu Maxx","Marauder","Mariner","Mariner Hybrid","Mark LT","Mark VII","Mark VIII","Matrix","Maxima","MAZDA3","MAZDA5","MAZDA6","MAZDASPEED MAZDA3","MAZDASPEED MAZDA6","MAZDASPEED MX-5 Miata","Mazdaspeed Protege","MDX","Metro","Mighty Max Pickup","Milan","Millenia","Mirage","MKS","MKX","MKZ","ML55 AMG","Monaco","Montana","Montana SV6","Monte Carlo","Montego","Monterey","Montero","Montero Sport","Mountaineer","MPV","MR2","MR2 Spyder","Murano","Murcielago","Mustang","Mustang SVT Cobra","MX-3","MX-5 Miata","MX-6","Mystique","Navajo","Navigator","Navigator L","Neon","Neon SRT-4","New Beetle","New Yorker","Nitro","NX","Oasis","Odyssey","Omni","Optima","Outback","Outlander","Outlook","Pacifica","Park Avenue","Park Ward","Paseo","Passat","Passport","Pathfinder","Patriot","Phaeton","Phantom","Phantom Drophead Coupe","Pickup","Pilot","Precis","Prelude","Previa","Prius","Prizm","Probe","Protege","Protege5","Prowler","PT Cruiser","Pulsar","Q5","Q7","Q45","Quattroporte","Quest","QX4","QX56","R-Class","R\/V 3500 Series","R8","R8-RS","R32","Rabbit","Raider","Rainier","Rally Wagon","Ram 50 Pickup","RAM 150","RAM 250","RAM 350","Ram Cargo","Ramcharger","Ram Pickup 1500","Ram Pickup 1500 SRT-10","Ram Pickup 2500","Ram Pickup 3500","Ram Van","Ram Wagon","Ranger","Range Rover","Range Rover Sport","RAV4","RDX","Reatta","Regal","Relay","Rendezvous","Reno","Ridgeline","Rio","Riviera","RL","Roadmaster","Roadster","Rodeo","Rodeo Sport","Rogue","Rondo","Routan","RS4","RS5","RS6","RSX","RX-7","RX-8","RX 300","RX 330","RX 350","RX 400h","S-10","S-10 Blazer","S-15","S-15 Jimmy","S-Class","S-Series","S-Type","S-Type R","S4","S5","S6","S8","S40","S55 AMG","S60","S60 R","S65 AMG","S70","S80","S90","S2000","Sable","Safari","Safari Cargo","Samurai","Santa Fe","Savana","Savana Cargo","SC 300","SC 400","SC 430","Scoupe","Sebring","Sedona","Sentra","Sephia","Sequoia","Seville","Shadow","Shelby GT500","Sidekick","Sienna","Sierra 1500","Sierra 1500 Classic","Sierra 1500HD","Sierra 1500HD Classic","Sierra 2500","Sierra 2500HD","Sierra 2500HD Classic","Sierra 3500","Sierra 3500 Classic","Sierra 3500HD","Sierra C3","Sierra Classic 1500","Sierra Classic 2500","Sierra Classic 3500","Sigma","Silverado 1500","Silverado 1500 Classic","Silverado 1500 SS","Silverado 1500 SS Classic","Silverado 1500HD","Silverado 1500HD Classic","Silverado 2500","Silverado 2500HD","Silverado 2500HD Classic","Silverado 3500","Silverado 3500 Classic","Silverado 3500HD","Silver Seraph","Sixty Special","Sky","Skylark","SL-Class","SL55 AMG","SL65 AMG","SLK-Class","SLK32 AMG","SLK55 AMG","SLR McLaren","SLX","Solstice","Sonata","Sonoma","Sorento","Spectra","Spirit","Sportage","Sportvan","Sprinter","Sprinter Cargo","SRX","SSR","Stanza","Stealth","Stratus","STS","STS-V","Stylus","Suburban","Sunbird","Sunfire","Superamerica","Supra","SVX","SX4","Syclone","T100","Tacoma","Tahoe","Tahoe Hybrid","Tahoe Limited\/Z71","Taurus","Taurus X","TC","tC","Tempo","Tercel","Terraza","Thunderbird","Tiburon","Tiguan","Titan","TL","Topaz","Torrent","Touareg","Touareg 2","Town and Country","Town Car","Tracer","Tracker","TrailBlazer","TrailBlazer EXT","Trans Sport","Traverse","Tribeca","Tribute","Tribute Hybrid","Trooper","Truck","TSX","TT","TT-RS","TTS","Tucson","Tundra","Typhoon","Uplander","V8","V8 Vantage","V12 Vanquish","V40","V50","V70","V70 R","V90","Van","Vanagon","Vandura","Vanwagon","VehiCROSS","Venture","Veracruz","Verona","Versa","Veyron","Vibe","Vigor","Villager","Viper","Vitara","Voyager","VUE","VUE Hybrid","Wagoneer","Windstar","Windstar Cargo","Wrangler","X-90","X-Type","X3","X5","X6","xA","xB","XC","XC70","XC90","xD","XF","XG300","XG350","XJ-Series","XJR","XK-Series","XKR","XL7","XLR","XLR-V","XT","Xterra","Yaris","Yukon","Yukon Denali","Yukon Hybrid","Yukon XL","Z3","Z4","Z8","Zephyr"];


// http://www.mooforum.net/help12/scroll-scroll-element-then-back-t814.html
 
/* A workaround for IE issues in mootools 1.2.1
 * - Recreates FX.Scroll() but utilises 1.2.0's getPosition/getOffset routines.
 */
Fx.Scroll2 = new Class({
 
    'Extends': Fx.Scroll,
 
    'styleString': Element.getComputedStyle,
    'styleNumber': function( element, style ) {
        return this.styleString(element, style).toInt() || 0;
    },
    'borderBox': function( element ) {
        return this.styleString(element, '-moz-box-sizing') == 'border-box';
    },
    'topBorder': function( element ) {
        return this.styleNumber(element, 'border-top-width');
    },
    'leftBorder': function( element ) {
        return this.styleNumber(element, 'border-left-width');
    },
    'isBody': function( element ) {
        return (/^(?:body|html)$/i).test(element.tagName);
    },
    'toElement': function( el ) {
        var offset   = {x: 0, y: 0};
        var element  = $(el);
       
        if (this.isBody(element)) {
            return offset;
        }
        var scroll = element.getScrolls();
        
        while (element && !this.isBody(element)){
            offset.x += element.offsetLeft;
            offset.y += element.offsetTop;
           
            if (Browser.Engine.gecko){
                if (!this.borderBox(element)){
                    offset.x += this.leftBorder(element);
                    offset.y += this.topBorder(element);
                }
                var parent = element.parentNode;
                if (parent && this.styleString(parent, 'overflow') != 'visible'){
                    offset.x += this.leftBorder(parent);
                    offset.y += this.topBorder(parent);
                }
            } else if (Browser.Engine.trident || Browser.Engine.webkit){
                offset.x += this.leftBorder(element);
                offset.y += this.topBorder(element);
            }
 
            element = element.offsetParent;
            if (Browser.Engine.trident) {
                while (element && !element.currentStyle.hasLayout) {
                    element = element.offsetParent;
                }
            }
        }
        if (Browser.Engine.gecko && !this.borderBox(element)){
            offset.x -= this.leftBorder(element);
            offset.y -= this.topBorder(element);
        }
       
        var relative = this.element;
        var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0};
        var position = {x: offset.x - scroll.x, y: offset.y - scroll.y};
       
        if(this && this.start) {
        	return this.start(position.x - relativePosition.x, position.y - relativePosition.y);
        }
    }
});

function emptyOverlay( group ) {
	if (group === undefined) {
		group = window.document;
	}
	
	// we cannot overlay on hidden fields. we need to determine size. so momentarily un-hide all hidden.
	var hidden = group.getElements('.Hide');
	hidden.each(function(div) {
		div.addClass('HideBehind'); // make visible, but under everything so they don't show while we get object sizes
	});
	
	// add 'empty' overlay and events to input fields
	group.getElements('.EmptyOverlay').each(function(div) {
		// if reinitializing, remove existing overlay
		var next = div.getNext();
		if (next !== null && next.hasClass('EmptyInputUnderlay')) {
			next.dispose();
		}
		
		// find text to use. eg: class="EmptyOverlay _Enter City_"
		var classes = div.className.match(/EmptyOverlay _(.*)_/);
		if (classes !== null) {
			emptyOverlaySet(div, classes[1]);
		}
	});
	
	// re-hide all hidden
	hidden.each(function(div) {
		div.removeClass('HideBehind');
	});
}

function emptyOverlaySet( div, text ) {
	
	// add 'empty' events to input fields
	if (div.id === '') {
		div.id = 'emptyInput' + div.uid;
	}
	
	var coord = div.getCoordinates();
	if(!coord.left || coord.left <= 0) { return; } // not visible, unable to position
	
	var underlay = new Element('span', {
		'class': 'EmptyInputUnderlay',
		'html': ' ' // MUST have content or the span drops in FireFox
	});
	
	var overlay = new Element('span', {
		'div': div.id,
		'html': text,
		'class': 'EmptyInputOverlay',
		'styles': {
			'left': -coord.width + 'px',
			'top' : 0,
			'width' : (coord.width - 10) + 'px',
			'height' : coord.height + 'px'
		},
		'events': {
			'click': function( ) { this.hide(); $(this.getAttribute('div')).focus(); }
		}
	});
	overlay.id = 'emptyOverlay' + overlay.uid;
	
	overlay.inject(underlay);
	underlay.inject(div, 'after');
	
	div.setAttribute('overlay', overlay.id);
	
	div.addEvents({
		'focus': function( ) { $(this.getAttribute('overlay')).hide(); },
		'blur': function( ) { if (this.value === '') {$(this.getAttribute('overlay')).show();}},
		'change': function( ) { var div = $(this.getAttribute('overlay')); if (this.value === '') {div.show();} else {div.hide();}}
	});
	
	if (div.value === '') {
		overlay.show();
	}
}




function numberUpDownFieldSetterClicked( e, div ) {
	var img = e.event.target ? e.event.target : e.event.srcElement;
	
	// get current value. if not a number, use minimum else incr/decr. respect minimum.
	var val = parseInt(div.value, 10);
	if (isNaN(val)) {
		val = div.min;
	} else {
		if (e.event.clientY < img.getTop() + img.getHeight() / 2) {
			++val;
		} else {
			--val;
		}
		
		// respect minimum even if user increments from negative number
		if (val < div.min) {
			val = div.min;
		}
	}
	
	div.value = val;
}

function numberUpDownFieldSetterChanged( e ) {
	// get current value. respect minimum.
	var val = parseInt(this.value, 10);
	if (typeof this.min !== 'undefined') {
		if (isNaN(val)) {
			val = this.min;
		} else {
			if (val < this.min) {
				val = this.min;
			}
		}
	} else if (isNaN(val)) {
		val = 0;
	}
	
	this.value = val;
}

function numberUpDownFieldSetter( ) {
	$$('.NumberUpDown').each(function( div ) {
		var min = parseInt(div.className, 10);
		if (!isNaN(min)) {
			div.min = min;
		}
		
		div.addEvent('change', numberUpDownFieldSetterChanged);
		
		var img;
		img = new Element('img', {
			'src': '/images/arrows-up-down.gif',
			'styles': {
				'vertical-align': 'middle',
				'cursor': 'pointer'
			},
			'class': '_JSFVimg IE6Hover',
			'events': {
				'click': function( e ) {numberUpDownFieldSetterClicked(e, div); e.stop();},
				'mousedown': function( e ) {e.stop();} // prevent dragging img
			}
		});
		img.inject(div, 'after');
	});
}

// ---------------- JSFV: JavaScript Form Validation -----------------------

var JSFV = {
	'_flashEnabled': false,	// prevent flashing on div init (init enables)
	
	'_type':	undefined,	// 1 required. all others optional but in order specified.
	'_upDown':  undefined,	// 2 "_ud"
	'_min':		undefined,	// 3 "_m999"
	'_max':		undefined,	// 4 "_x999"
	'_default':	undefined,	// 5 "_d999"
	'_step':	1,			// 6 "_s999"
	'_decimals': undefined,	// 7 "_e999"
	
	'_inChange': false,		// inside _change() call -- do not recurse
	
	'setter': function( ) {
		$$('._JSFV').each(function( div ) {
			JSFV.init(div);
		});
	},
	
	'init': function ( div ) {
		$extend(div, this);
		
		// get highlighting span
		div.highlightSpan = div.getParent();
		if (!div.highlightSpan || div.highlightSpan.tagName !== 'SPAN' || div.highlightSpan.id.search(/highlight/i) === -1) {
			div.highlightSpan = null;
		}
		
		var matches = div.className.match(/JSFVset_(-?[.a-z0-9]+)_?(ud)?_?m?(-?[.0-9]*)?_?x?(-?[.0-9]*)?_?d?(-?[.0-9]*)?_?s?(-?[.0-9]*)?_?e?(-?[.0-9]*)?/);
		if (matches && matches[1]) {
			div._type = matches[1];
			div._upDown = matches[2] === 'ud';
			
			if (matches[3] !== undefined && matches[3] !== '') {
				div._min = div._fixVal(matches[3]);
			}
			if (matches[4] !== undefined && matches[4] !== '') {
				div._max = div._fixVal(matches[4]);
			}
			if (matches[5] !== undefined && matches[5] !== '') {
				div._default = div._fixVal(matches[5]);
			}
			if (matches[6] !== undefined && matches[6] !== '') {
				div._step = div._fixVal(matches[6], true);
			}
			if (matches[7] !== undefined && matches[7] !== '') {
				div._decimals = parseInt(matches[7], 10);
			}
		}
		
		// add up/down image if not already there (may be in cloned div)
		if (div._upDown) {
			var img = div.getNext();
			if (!img || !img.hasClass('_JSFVimg')) {
				img = new Element('img', {
					'src': '/images/arrows-up-down.gif',
					'class': '_JSFVimg IE6Hover'
				});
				img.inject(div, 'after');
			}
			
			img.addEvents({
				'click': function( e ) {div._clicked(e); e.stop();},
				'mousedown': function( e ) {e.stop();} // prevent dragging img
			});
		}
		
		div.addEvents({
			'change': div._changed,
			'keypress': function(e) {
				switch (e.code) {
					case 38:
						this._updown(true);
						break;
					case 40:
						this._updown(false);
						break;
					default:
						break;
				}
			}
		});
		div._changed(); // force to be valid
		
		div._flashEnabled = true;
	},
	
	'_changed': function( e ) {
		if (this._inChange) {
			return;
		}
		this._inChange = true;
		
		var oldVal = this.value;
		
		// get current value. respect minimum.
		this.value = this._fixVal(oldVal);
		if (this.value != oldVal) {
			this.fireEvent('change'); // fire any other attached change event
		}
		
		this._highlight(this.value != 0);
		
		this._inChange = false;
	},
	
	'_clicked': function ( e ) {
		// get the arrow image that was clicked
		var img = e.event.target ? e.event.target : e.event.srcElement;
		
		// determine whether up or down arrow clicked
		var y = e.event.pageY || e.event.clientY + window.document.getScroll().y;
		var up = y < img.getTop() + img.getHeight() / 2;
		
		// do the incr/decr
		this._updown(up);
	},
	
	'_updown': function ( up ) {
		// get current value. if not a number, use minimum else incr/decr. respect minimum.
		var val = this._fixVal(this.value);
		if (isNaN(val)) {
			if (typeof this._default !== 'undefined') {
				val = this._default;
			} else {
				val = 0; // if invalid and no minimum, up/down goes to zero
			}
		} else {
			if (up === true) {
				val += this._step;
			} else {
				val -= this._step;
			}
			val = this._fixVal(val);
		}
		
		this.value = val;
		
		this.fireEvent('change'); // announce the change
	},
	
	'_fixVal': function( val, ignoreRange ) {
		ignoreRange = ignoreRange | false;
		var oldVal = val;
		
		switch (this._type) {
			case 'int':
				if (typeof val === 'string') {
					val = val.replace(/[$,]/g, '');
				}
				val = parseInt(val, 10);
				if (!ignoreRange) {
					val = this._enforceRange(val);
				}
				
				if (this._flashEnabled && parseInt(oldVal, 10) != val) {
					this.blink();
				}
				break;
			case 'float':


// [ ] flashes when fixing rounding error on incr/decr w/ step 0.2.
//			??? parseFloat and if same as old, make rounded number the oldVal ???


				if (typeof val === 'string') {
					val = val.replace(/[$,]/g, '');
				}
				val = parseFloat(val);
				if (isNaN(val)) {
					val = '';
				} else {
					if (typeof this._decimals !== 'undefined') {
						if (this._decimals <= 0) {
							val = Math.round(val);
						} else {
							var factor = Math.pow(10, this._decimals);
							val = Math.round(val * factor) / factor;
							
							// add zeros to fill decimal places
							val = val.toString();
							var decimals = val.match(/\.([0-9]*)$/);
							var z = this._decimals;
							if (decimals && decimals[1]) {
								z -= decimals[1].length;
							} else {
								val += '.';
							}
							// add trailing zeros
							for ( ; z > 0; --z) {
								val += '0';
							}
						}
					}
				}
				
				if (!ignoreRange) {
					val = this._enforceRange(val);
				}
				
				if (this._flashEnabled && parseFloat(oldVal) != parseFloat(val)) {
					this.blink();
				}
				
				break;
			default:
				break;
		}
		
		return val;
	},
	
	'_enforceRange': function( val ) {
		if (isNaN(val)) {
			if (typeof this._default !== 'undefined') {
				val = this._default;
			} else {
				val = '';
			}
		} else if (typeof this._min !== 'undefined' && val < this._min) {
			val = this._min;
		} else if (typeof this._max !== 'undefined' && val > this._max) {
			val = this._max;
		}
		
		return val;
	},
	
	'blink': function( ) {
		var _this = this;
		_this.addClass('Flash');
		(function( ) {
			_this.removeClass('Flash');
			(function( ) {
				_this.addClass('Flash');
				(function( ) {_this.removeClass('Flash');}).delay(250);
				}).delay(250);
		}).delay(250);
	},
	
	'_roundCents': function( val ) {
		val = Math.round(val * 100);
		var cents = val % 100;
		cents = cents.toString();
		switch (cents.length) {
			case 0:
				cents = '00';
				break;
			case 1:
				cents = '0' + cents;
				break;
			default:
				break;
		}
		return Math.floor(val / 100) + '.' + cents;
	},
	
	'_highlight': function( on ) {
		if (this.highlightSpan && this.highlightSpan !== null) {
			if (on === true) {
				this.highlightSpan.addClass('yellowHighlighter');
			} else {
				this.highlightSpan.removeClass('yellowHighlighter');
			}
		}
	}
};

// -------------- FLOATER -----------------
// * on startup, verify floaters are on screen and not overlapping form fields .each(reposition())
// * for floaters that are flagged to minimize, minimize and add click event -- class includes CdFloaterMin
// * on window resize, reposition floaters so on screen and not overlapping form fields .each(reposition())

function CdFloaters( ) {
	this.floaters = [];
	this.init();
}

CdFloaters.prototype.init = function( ) {
	// process each floater
	$$('.info-floater-needhelp').each((function( div ) {
		this.floaters.push(div); // keep track of div for repositioning
		
		addEvent('click',function( ) {
			div.style.display = 'none';
			div.getNext().style.display = 'block';
		});
	}).bind(this));
	$$('.info-floater-collapsible').addEvent('click', function( ) {
		this.style.display = 'none';
		this.getPrevious().style.display = 'block';
	});
	
	// if any floaters, add resize event to window.document
	if (this.floaters.length !== 0) {
		window.addEvent('resize', (function( ) {
			this.floaters.each((function( floater ) {
				this.reposition(floater);
			}).bindWithEvent(this));
		}).bindWithEvent(this));
	}
	
	
};

CdFloaters.prototype.makeClickable = function( ) {
	// add 'click' events to help floaters
	$$('.info-floater-collapsible').each(function( div ) {
		div.addEvent('click', (function( ) {
			this.style.display = 'none';
			this.getNext().style.display = 'block';
		}).bind(div));
		
		var closed = new Element('div', {
			'html': '<div class="info-floater-needhelp"><h1>Need Help?</h1></div>'
		});
		
		closed.inject(div, 'after');
		closed.addEvent('click', function( ) {
			closed.style.display = 'none';
			closed.getPrevious().style.display = 'block';
		});
	});
};

CdFloaters.prototype.reposition = function( floater ) {
	
	
};



function floatersInit( ) {
	// add 'click' events to help floaters
	$$('.info-floater-needhelp').addEvent('click', function( ) {
		this.style.display = 'none';
		this.getNext().style.display = 'block';
	});
	$$('.info-floater-collapsible').addEvent('click', function( ) {
		this.style.display = 'none';
		this.getPrevious().style.display = 'block';
	});
}



// ---------------- CdVehicles: Controller for Vehicle Entry Rows -----------------------

function CdVehicleListings( ) {
	var divs = $$('.VehicleListing');
	
	if (divs.length !== 0) {
		this.maxId = null;
		this.template = null;
		
		this.listings = {};
		divs.each(function(div) {
			this.maxId = div.getElement('.FatCity').id;
//console.log('id', this.maxId);
			// get id integer value
			this.maxIdInt = this.maxId.replace(/[^0-9]/g, ''); // requires ID to have a single integer such as "Origination_0" ("0") NOT "Orig_1_part_0" ("10")
			
			// if integer is zero then use this as template
			if (this.maxIdInt === '0') {
				this.template = div;
				
				// remove existing state text input
//console.log("div.getElements('.FatLocation')", div.getElements('.FatLocation'));
				(function() {
					div.getElements('.FatLocation').each(function( fieldset ) {
//console.log('fieldset', fieldset);
//console.log("fieldset.getElements('.FatStateText')", fieldset.getElements('.FatStateText'));
						fieldset.getElements('.FatStateText').each(function( div ) {
							div.getNext().dispose();
							div.dispose();
						});
						
						// make state selector visible so it can correctly be made small
						fieldset.getElement('.FatStateSmall').style.display = '';
					});
					
					div.addClass('Hide'); // required for IE
					div.removeClass('HideBehind'); // required for IE
				}).delay(250); // make sure short state has been added before trying to remove
			} else {
				this.listings[this.maxId] = new CdVehicles(div);
			}
			
//console.log('max', this.maxId, this.maxIdInt);
		}, this);
	}
}


/*
 * Add a listing from the template -- update the ID and various junk that is usually initialized on page load
 * Required for Post Multiple to add another listing div
 */
CdVehicleListings.prototype.addListing = function( ) {
	if (this.template) {
		if (this.maxIdInt >= 10) {
			alert('Please submit the form at this time.\nYou cannot have more than 10 listings on this form.');
			return;
		}
		
		// create a new listing
		var newListing = new CdVehicles(this.template.clone());
		
		// inject into form
		var last = this.listings[this.maxId];
		newListing.group.inject(last.group, 'after');
		
		// set the field names and city id
		++this.maxIdInt;
		var cityId = newListing.changeListingId(this.maxIdInt);
		
		// add to our array
		this.listings[cityId] = newListing;
		
		// save new last
		this.maxId = cityId;
		
		// show the listing
		newListing.group.removeClass('Hide');
		newListing.group.addClass(this.maxIdInt % 2 === 0 ? 'Even' : 'Odd');
		
		/*
		 * initialize a bunch of stuff
		 */
		
		// init location field sets
		newListing.group.getElements('.FatLocation').each(function( fieldset ) {
			new FatLocationFieldset({
				city: fieldset.getElement('.FatCity'),
				state: fieldset.getElement('.FatState'),
				zip: fieldset.getElement('.FatZip'),
				metro: fieldset.getElement('.FatMetro'),
				valid: fieldset.getElement('.FatValid'),
				clear: fieldset.getElement('.FatClear'),
				spinner: fieldset.getElement('.FatSpinner'),
				manager: FatManager
			});
		});
		
		// add empty overlays
		emptyOverlay(newListing.group);
		
		// enable auto-validation fields
		JSFV.init(newListing.vehicles[0].year); // the first vehicle entry
		JSFV.init(newListing.vehicles[0].qty);
		
		// initialize "Check Prices" link
		var cp = newListing.group.getElement('.mbLink');
		if (cp !== null) { // (allow Sample Prices to be off)
			setEditorSamplePricesDiv(FatManager, cp);
			
			// attach to multibox
			initMultiBox.startEl(cp);
			initMultiBox.addListeners();
		}
		
		// enable calendar
		var calendar = newListing.group.getElement('.CalendarInput');
		calendar.removeClass('calendar');
		var sib = calendar.getNext('.calendar');
		if (sib) {
			sib.dispose();
		}
		
		initCalendarDiv(calendar); // initialize calendar
		
		// fix quickpay & comchek
		var maxIdInt = this.maxIdInt;
		var div = newListing.group.getElement('.COD');
		div.id = 'cod' + maxIdInt;
		div = div.getNext();
		div.id = 'cod_where' + maxIdInt;
		
		div = newListing.group.getElement('.QuickPay');
		var cb = div.getElement('input');
		var prompt = cb.getNext();
		
		div.onmouseover = function() {showTooltip('quickpay_check' + maxIdInt, 'quickpay_tooltip');};
		cb.onclick = function() {evaluateCheckbox('quickpay', maxIdInt);};
		cb.id = 'quickpay_check' + this.maxIdInt;
		prompt.htmlFor = 'quickpay_check' + this.maxIdInt;

		div = newListing.group.getElement('.ComChek');
		cb = div.getElement('input');
		prompt = cb.getNext();
		
		maxIdInt = this.maxIdInt;
		div.onmouseover = function() {showTooltip('comchek_check' + maxIdInt, 'comchek_tooltip');};
		cb.onclick = function() {evaluateCheckbox('comchek', maxIdInt);};
		cb.id = 'comchek_check' + this.maxIdInt;
		prompt.htmlFor = 'comchek_check' + this.maxIdInt;
		
		// focus to city
		$(this.maxId).focus();
		
		// remove "add" button if form full
		if (this.maxIdInt >= 10) {
			var addButton = $('CdVehicleListingsAddListing');
			var notice = new Element('span', {html: 'There is a limit of 10 listings on this form. Click "Post Vehicles" when ready.'});
			notice.inject(addButton, 'after');
			addButton.dispose();
		}
	}
};

CdVehicles.prototype.changeListingId = function( id ) {
	// change city ids
	var cities = this.group.getElements('.FatCity');
	cities[0].id = 'Origination_' + id;
	cities[1].id = 'Destination_' + id;
	
	// change name in all inputs
	var fields = this.group.getElements('input,select');
	fields.each(function( field ) {
		field.name = field.name.replace(/0/, id);
	});
	
	return cities[0].id;
};


/* 
 * Creates a CdVehicles controller and creates CdVehicle objects found on page.
 * Searches for objects with SPECIFIC CLASS.
 * 
 * CdVehicle -- Outer wrapper (div, tr, etc.) for a vehicle field group. Creates CdVehicle object and adds to list.
 * Template -- [optional] In ONE FIELD GROUP, when combined with CdVehicle class designates a blank group for "Add Vehicle".
 *			A template must exist to enable "Add Vehicle" functionality.
 *			Each template field name must include "-9999" where a unique new vehicle Id is to be placed.
 *			When a new vehicle group is created from the template, "-9999" is replaced with new vehicle Id "-1" or lower.
 * 
 * CdVehiclesAddLink -- [optional] Span that has "Add Vehicle" text. Event is added to handle click.
 * CdVehiclesTotalQty -- [optional] Span for displaying total vehicle count. Updated by controller.
 * CdVehiclesMode -- [optional] Two radio buttons on form controls "moreMode" availability of "moreDiv" fields.
 * 			Events are added to enable/show or disable/hide moreDiv fields and "More" links when buttons clicked.
 *			Allows the Post Vehicle form to have "Post Only" (no "More") and "Post and Store Data for Dispatch" (with "More").
 */

function CdVehicles( group ) {
	this.group = group;
	
	this.nextVehicleId = -1;
	
	this.vehicles = [];
	this.template = null;
	this.moreFields = [];
	
	this.priceNote = group.getElement('.PriceNote');
	
	var vehicles = group.getElements('.CdVehicle');
	
	if (vehicles.length === 0) {	// if no vehicle groups, don't try to initialize
		return;
	}
	
	this.totalQty = group.getElement('.CdVehiclesTotalQty');
	this.totalQtyInput = group.getElement('.CdVehiclesTotalQtyInput');
	this.addLink = group.getElement('.CdVehiclesAddLink');
	if (this.addLink) {
		this.addLink.addClass('IE6Hover');
		this.addLink.addEvent('click', (function( e ) {this.add();}).bindWithEvent(this));
	}
	
	vehicles.each((function( div ) {
		if (div.hasClass('Template')) {
			this.template = div;
			
			// determine "more" fields to force visible if validation fails
			var moreDiv = this.template.getElements('.MoreDiv');
			if (moreDiv) {
				var mores = moreDiv.getElements('input,select');
				if(mores.length > 0) {
					mores[0].each((function ( infield ) {
						this.moreFields.push(infield.className.split(' ')[0]);
					}).bind(this));
				}
			}
		} else {
			this.addVehicle(div);
		}
	}).bind(this));
	
	// if exists on form, find radio buttons that control availability of moreDiv fields. 
	// "Post Only" turns off. "Post & Store Data for Dispatch" allows additional fields.
	this.moreMode = group.getElements('.CdVehiclesMode');
	if (typeof this.moreMode === 'object' && this.moreMode.length === 2) {
		this.moreMode[0].addEvent('click', (function( e ) {
			var input = e.event.target ? e.event.target : e.event.srcElement;
			this.showMore(input.value);
		}).bindWithEvent(this));
		
		this.moreMode[1].addEvent('click', (function( e ) {
			var input = e.event.target ? e.event.target : e.event.srcElement;
			this.showMore(input.value);
		}).bindWithEvent(this));
	}
	
	this.setTotal();
}

CdVehicles.prototype.addVehicle = function( div ) {
	var vehicle = new CdVehicle(this, div);
	this.vehicles.push(vehicle);
	
	// register to change total with any vehicle qty change
	if (this.totalQty && vehicle.qty) {
		vehicle.qty.addEvent('change', (function( e ) {this.setTotal();}).bind(this));
	}
	
	return vehicle;
};

CdVehicles.prototype.add = function( ) {
	if (this.template) {
		var newVehicle = this.template.clone();
		newVehicle.removeClass('Template');
		
		var last = this.vehicles[this.vehicles.length-1].div;
		newVehicle.inject(last, 'after');
		
		var vehicle = this.addVehicle(newVehicle);
		vehicle.changeVehicleId(this.nextVehicleId);
		
		// update for next vehicle
		--this.nextVehicleId;
		
		vehicle.removed.defaultValue = '1'; // Allow "leaving page" check to know a vehicle was added. If vehicle removed, the change is ignored.
		vehicle.removed.value = '0'; // mark as not being removed
		
		if (vehicle.year && vehicle.year.hasClass('_JSFV')) {	// ensure year is int
			JSFV.init(vehicle.year);
		}
		if (vehicle.qty && vehicle.qty.hasClass('_JSFV')) {	// set up Qty up/down arrows in new vehicle field group
			JSFV.init(vehicle.qty);
		}
		
		this.showRemove();
		this.setTotal();
		
		vehicle.year.focus(); // move focus to year field
	}
};

// remove a vehicle from the list, remove fields, flag removed, recalc everything
CdVehicles.prototype.remove = function( vehicle ) {
	if (this.vehicles.length < 2) {		// maintain at least one vehicle
		return;
	}
	
	// if something was entered, confirm removal
	if (vehicle.year.value !== '' || vehicle.make.value !== '' || vehicle.model.value !== '') {
		if (!confirm('Are you sure you want to permanently remove this vehicle?')) {
			return;
		}
	}
	
	var vNum = this.vehiclesNum(vehicle);
	if (vNum > -1) {
		this.vehicles.splice(vNum, 1);	// remove from the vehicle list
	}
	
	vehicle.fieldsDiv.dispose(); // Drop field wrapper. HTML may leave hidden ID field outside "fields".
	vehicle.div.removeClass('CdVehicle');
	
	if (vehicle.removed) {
		vehicle.removed.value = 1;	// flag as removed in hidden field
	}
	
	this.showRemove();
	this.setTotal();
};

// show or hide "remove" links
CdVehicles.prototype.showRemove = function( ) {
	// show "remove" if more than one vehicle else hide
	var show = this.vehicles.length > 1;
	this.vehicles.each(function( vehicle ) {
		if (show) {
			vehicle.remove.removeClass('Hide');
		} else {
			vehicle.remove.addClass('Hide');
		}
	});
};

// show or hide "moreDiv" fields
CdVehicles.prototype.showMore = function( more ) {
	more = parseInt(more, 10);
	this.vehicles.each(function( vehicle ) {
		vehicle.showMore(more);
	});
	
	// also set template so added vehicles are same
	this.showMoreTemplate(more);
};

// set template moreDiv so future added vehicles are same
CdVehicles.prototype.showMoreTemplate = function( more ) {
	var moreLink = this.template.getElements('.More')[0];
	if (more) {
		moreLink.removeClass('Hide');
	} else {
		moreLink.addClass('Hide');
	}
};

// calcuate and set the total quantity
CdVehicles.prototype.setTotal = function( ) {
	if (this.totalQty) {
		var total = 0;
		this.vehicles.each(function( vehicle ) {
			if (vehicle.qty) {
				total += parseInt(vehicle.qty.value, 10);
			} else {
				++total;
			}
		});
		
		this.totalQty.innerHTML = total;
		
		this.totalQtyInput.value = total;
		
		if (this.priceNote !== null) {
			if (total === 1) {
				this.priceNote.innerHTML = '';
			} else {
				this.priceNote.innerHTML = 'Use full amount of load for Price';
			}
		}
	}
};

// option to enable/hide "More" detail information
CdVehicles.prototype.moreMode = function( mode ) {
	
	
	
};

CdVehicles.prototype.vehiclesNum = function( vehicle ) {
	for (var x = 0; x < this.vehicles.length; ++x) {
		if (this.vehicles[x] === vehicle) {
			return x;
		}
	}
	
	// no match
	return -1;
};

CdVehicles.prototype.validate = function( ) {
	var allErrors = [];
	if (this.vehicles.length === 0) {
		errors.push('There must be at least one vehicle.');
	} else {
		for (var x = 0; x < this.vehicles.length; ++x) {
			var newErrors = this.vehicles[x].validate(x);
			allErrors = allErrors.concat(newErrors);
		}
	}
	
	return allErrors;
};


// ---------------- CdVehicle: Single Vehicle Entry Row -----------------------

/* 
 * Creates one CdVehicle objects. Searches for objects with SPECIFIC CLASS within the passed wrapper div.
 * 
 * Form elements inside of CdVehicle wrapper are found using these classes:
 * Id		-- Hidden field with vehicle_id. TEMPLATE MUST HAVE VALUE "-9999". Added vehicles are "-1" and lower.
 * Removed	-- Hidden field to flag that a vehicle has been removed.
 * 
 * Fields	-- Wrapper of all fields that will be dropped when a vehicle is removed. (Wraps everything but two above.)
 * 
 * Year		-- Year input
 * Make		-- Make input
 * Model	-- Model input
 * Type		-- Type input. Uses JT type numbers. If "Other" then "Other" field below is enabled if exists.
 * Qty		-- Qty field. (On dispatches, this should not be included.)
 * More		-- Span with text to open "moreDiv" fields. Span text is toggled between "More" and "Less".
 * Remove	-- Span with text to remove this vehicle. If only one vehicle group exists, "Remove" is hidden and disabled.
 * 
 * MoreDiv	-- Wrapper (inside "Fields") that has additional information "More" fields.
 *				This portion is hidden/shown with More/Less link and hidden/disabled if moreMode is off (CdVehiclesMode).
 * OtherHead -- Header/prompt for "Vehicle Type Other" field. "Required" class is added when Type is set to "Other"
 * Other	-- Other Vehicle Type input. Disabled unless Type is "Other", then required.
 * Color	-- Color input.
 * Plate	-- Plate number input.
 * State	-- Plate state input.
 * Lot		-- Lot number input.
 * Vin		-- VIN input.
 */

function CdVehicle( controller, div ) {
	this.controller = controller;
	
	this.div = div;
	
	this.id = div.getElement('.Id');
	this.removed = div.getElement('.Removed');
	
	this.fieldsDiv = div.getElement('.Fields');
	
	this.year = div.getElement('.Year');
	this.make = div.getElement('.Make');
	this.model = div.getElement('.Model');
	this.type = div.getElement('.Type');
	this.qty = div.getElement('.Qty');
	this.more = div.getElement('.More');
	this.remove = div.getElement('.Remove');
	
	this.moreDiv = div.getElement('.MoreDiv');
	this.otherHead = div.getElement('.OtherHead');
	this.other = div.getElement('.Other');
	this.color = div.getElement('.Color');
	this.plate = div.getElement('.Plate');
	this.state = div.getElement('.State');
	this.lot = div.getElement('.Lot');
	this.vin = div.getElement('.Vin');
	
	new vehicleAutoSuggest( this.make, this.model, this.type );
	
	this.remove.addEvent('click', (function( e ) {
		this.controller.remove(this);
	}).bindWithEvent(this));
	
	// add hover for IE6
	initIE6Hover(this.remove);
	initIE6Hover(this.more);
	
	if (this.more) {
		this.more.addEvent('click', (function( e ) {
			this.moreLess(!this.more.hasClass('Less'));
		}).bindWithEvent(this));
	}
	
	this.type.addEvent('change', (function( e ) {
		if (this.moreDiv) {
			if (this.type.value === 'Other') {
				this.moreLess(1); // force more visible
				this.other.removeClass('disabled'); // for IE
				this.otherHead.addClass('Required');
				this.other.disabled = false;
			} else {
				this.otherHead.removeClass('Required');
				this.other.addClass('disabled'); // for IE
				this.other.style.backgroundColor = ''; // make sure not flagged as invalid
				this.other.value = '';
				this.other.disabled = true;
			}
		}
	}).bindWithEvent(this));
	
	
	this.type.fireEvent('change'); // make sure "other" enabling is correct
}

CdVehicle.prototype.showMore = function( more ) {
	// show or hide "more" fields based on toggle
	if (more) {
		this.more.removeClass('Hide');
	} else {
		this.moreLess(0);
		this.more.addClass('Hide');
		this.moreDiv.addClass('Hide');
	}
};

CdVehicle.prototype.moreLess = function( more ) {
	if (this.moreDiv && this.more && !this.more.hasClass('Hide')) {
		if (more) {
			this.more.addClass('Less');
			this.moreDiv.removeClass('Hide');
			this.more.innerHTML = 'Less';
		} else {
			this.more.removeClass('Less');
			this.moreDiv.addClass('Hide');
			this.more.innerHTML = 'More';
		}
	}
};

CdVehicle.prototype.changeVehicleId = function( id ) {
	var fields = this.div.getElements('input,select');
	fields.each(function( field ) {
		field.name = field.name.replace(/-9999/, id);
	});
};

CdVehicle.prototype.validate = function( num ) {
	// see whether "more" option is available
	var moreAvailable = this.more && !this.more.hasClass('Hide');
	
	// Make sure all Required fields are filled.
	// Find all prompts with Required class.
	// Check next element (which must be the input).
	var errors = [];
	this.div.getElements('.Required').each((function( req ) {
		var field = req.getNext();
		
		// If there's no next, it's in a table. Get field from next <td>.
		if (field === null) {
			field = req.getParent().getNext().getChildren()[0];
		}
		
		// if can't get field, ignore validation
		if (field === null || typeof field === 'undefined' || typeof field.value === 'undefined') {
			return;
		}
		
		var fieldName = field.className.split(' ')[0];
		var isMoreField = this.controller.moreFields.indexOf(fieldName) > -1;
		
		// required field cannot be empty unless "more" not available and is this is a "more" field
		if (field.value === '' && (moreAvailable || !isMoreField)) {
			errors.push('Vehicle #' + (num + 1) + ' must have ' + fieldName + ' provided.');
			field.addClass('FieldError');
			
			// if error is in More fields, show fields
			if (isMoreField && !this.more.hasClass('Less')) {
				this.moreLess(1);
			}
		} else {
			field.removeClass('FieldError');
		}
	}).bind(this));
	
	if (this.qty !== null) {
		if (this.qty.value < 1 || this.qty.value > 255) {
			errors.push('Vehicle #' + (num + 1) + ' Qty must be between 1 and 255.');
			this.qty.addClass('FieldError');
		} else {
			this.qty.removeClass('FieldError');
		}
	}
	
	// check year between 1850 and 2050
	if (this.year.value !== '' && (this.year.value < 1850 || this.year.value > 2050)) {
		errors.push('Vehicle #' + (num + 1) + ' Year must be between 1850 and 2050.');
		this.year.addClass('FieldError');
	}
	
	return errors;
};

// ----------------------------------------------------------------

//function CdPostFormPayController( options  ) {
////console.log('CdPostFormPayController', options, $$('.PayGroup'));
//	this.quickpayAcknowledged = options.qpAck;
//	this.comchekAcknowledged = options.ccAck;
//	
//	this.groups = [];
//	
//	$$('.PayGroup').each((function( group ) {
////console.log('CdPostFormPayController', group, this);
//		this.groups.push(new CdPostFormPay(group, this));
//	}).bind(this));
//}
//
//CdPostFormPayController.prototype.prompts = {
//	'comchek': {
//		'prompt': 'You have selected "Comchek". By checking this box you are agreeing to pay the carrier using a Comchek authorization number. Failure to provide payment in this matter may be grounds for a negative rating and/or dismissal from CentralDispatch.',
//		'agree': 'I agree to pay the Carrier via Comchek',
//		'cancel': 'Cancel - Do not use Comchek',
//		'name': 'Comchek'
//	},
//	'quickpay': {
//		'prompt': 'You have selected "Quick Pay". By checking this box you are agreeing to pay the carrier within 48 hours of the carrier providing to you a signed Bill of Lading (BOL). Failure to provide payment in this matter may be grounds for a negative rating and/or dismissal from CentralDispatch.',
//		'agree': 'I agree to pay the Carrier via Quick Pay',
//		'cancel': 'Cancel - Do not use Quick Pay',
//		'name': 'Quick Pay'
//	}
//};
//
//function CdPostFormPay( group, controller ) {
//	this.group = group;
//	this.controller = controller;
//	
//	this.quickpay = group.getElement('.QuickPay');
//	if (!this.quickpay) {
//		return;
//	}
//	
//	this.comchek = group.getElement('.ComChek');
//	if (!this.comchek) {
//		return;
//	}
//	
//	this.quickpayInput = this.quickpay.getElement('input');
//	this.quickpayTip = null;
//	
//	this.comchekInput = this.comchek.getElement('input');
//	this.comchekTip = null;
//	
//	this.init();
//}
//
//CdPostFormPay.prototype.init = function( ) {
//		this.quickpayInput.addEvent('click', function(e) {evaluateCheckbox('quickpay');});
//		
//		this.quickpayTip = new Element('div', {
//			
//		});
//		
//		this.quickpay.addEvents({
//			'mouseover': function(e) {showTooltip(checkbox, 'quickpay_tooltip');},
//			'mouseout': function(e) {hideTooltip('quickpay_tooltip');}
//		});
//};


// ----------------------------------------------------------------

function CdPostFormController( ) {
	this.initRadios();
}

CdPostFormController.prototype.initRadios = function( ) {
	// if exists on form, find radio buttons that control availability of DispatchFields divs. 
	var moreMode = $$('.CdVehiclesMode');
	if (typeof moreMode === 'object' && moreMode.length === 2) {
		moreMode[0].addEvent('click', function( e ) {
			$$('.DispatchFields').each(function( div ) {
				div.addClass('Hide');
			});
		});
		
		moreMode[1].addEvent('click', function( e ) {
			$$('.DispatchFields').each(function( div ) {
				div.removeClass('Hide');
			});
		});
		
		// if in Post Only mode, hide DispatchFields
		if (moreMode[0].checked) {
			$$('.DispatchFields').each(function( div ) {
				div.addClass('Hide');
			});
		}
	}
};



// ----------------------------------------------------------------


function CdSearchVehicleTypes( selectedTypes ) {
	this.typesDiv = null;
	this.checkboxes = [];
	this.clearDiv = null;
	
	this.span = $$('.CdVehicleTypes')[0];
	if (!this.span) {
		return;
	}
	this.defaultHTML = this.span.innerHTML;
	
	this.span.addEvents({
		'click': (function( e ) {
			if (this.typesDiv.hasClass('Hide')) {
				this.typesDiv.removeClass('Hide');
				
				// if IE6, unhide sort2 selector
				if (IsIe6Browser === true) {
					$(document.forms['srchForm']['sort2']).addClass('Hide');
				}
			} else {
				this.hide();
			}
			e.stopPropagation();
		}).bindWithEvent(this)
	});
	
	// hide options div if click elsewhere
	window.document.addEvents({
		'click': (function( e ) {
			this.hide();
		}).bindWithEvent(this),
		'keydown': (function(e) {
			this.hide();
		}).bindWithEvent(this)
	});
	
	// get highlighting span
	this.highlightSpan = this.span.getParent();
	if (!this.highlightSpan || this.highlightSpan.tagName !== 'SPAN' || this.highlightSpan.id.search(/highlight/i) === -1) {
		this.highlightSpan = null;
	}
	
	this.initTypes(selectedTypes);
	
	this.addClear(); // add a "Clear" link
	
	this.hide(); // initialize span wording if something selected
}

/* 
 * Vehicle Group Types pulled from DB
 * 
	SELECT CONCAT("'", name, "',") type
	FROM vehicle_type_groups
	WHERE vehicle_type_group_id > 0
	ORDER BY ordernum;
 */
CdSearchVehicleTypes.prototype.types = [
	'Boat',
	'Car',
	'Motorcycle',
	'Pickup',
	'RV',
	'SUV',
	'Travel Trailer',
	'Van',
	'Other'
];

CdSearchVehicleTypes.prototype.initTypes = function( selectedTypes ) {
	var dim = this.span.getCoordinates();
	
	this.typesDiv = new Element('div', {
		'class': 'CdVehicleTypesDiv Hide',
		'styles': {
			'left': (dim['left'] - 15) + 'px',
			'top': (dim['top'] + dim['height'] - 16) + 'px'
		}
	});
	
	this.typesDiv.inject(this.span, 'after');
	
	var close = new Element('div', {
		'class': 'CdVehicleTypesClose',
		'html': '[close]'
	});
	close.inject(this.typesDiv, 'bottom');
	
	this.types.each((function(type) {
		var checked = selectedTypes.indexOf(type) > -1;
		this.makeTypeDiv(type, checked).inject(this.typesDiv, 'bottom');
	}).bind(this));
	
	var unknown = new Element('div', {
		'class': 'CdVehicleTypesUnknown',
		'html': '"Unknown" always included'
	});
	unknown.inject(this.typesDiv, 'bottom');
};

CdSearchVehicleTypes.prototype.makeTypeDiv = function( type, checked ) {
	var div = new Element('div', {'html': ' ' + type});
	
	var id = 'vehicle_types_' + type;
	var cb = new Element('input', {
		'type': 'checkbox',
		'name': 'vehicle_types[]',
		'id': id,
		'value': type
	});
	
	cb.addEvent('click', function(e) {
		e.stopPropagation();
	});
	cb.inject(div, 'top');
	cb.checked = checked;
	
	div.addEvent('click', function(e) {
		cb.checked = !cb.checked;
		e.stopPropagation();
	});
	
	this.checkboxes.push(cb);
	
	return div;
};

CdSearchVehicleTypes.prototype.hide = function( ) {
	if (!this.typesDiv.hasClass('Hide')) {
		this.typesDiv.addClass('Hide');
		
		// if IE6, unhide sort2 selector
		if (IsIe6Browser === true) {
			$(document.forms['srchForm']['sort2']).removeClass('Hide');
		}
	}
	
	var selected = this.somethingChecked();
	
	if (selected.selected === 0) {
		this.span.innerHTML =  this.defaultHTML;
		this.clearDiv.hide();
		this.highlight(false);
	} else if (selected.selected === 1) {
		this.span.innerHTML =  '<b>"' + selected.types[0] + '" Only</b>';
		this.clearDiv.show();
		this.highlight(true);
	} else {
		this.span.innerHTML =  '<b>' + selected.selected + ' Types Selected</b>';
		this.clearDiv.show();
		this.highlight(true);
	}
};

CdSearchVehicleTypes.prototype.highlight = function( on ) {
	if (this.highlightSpan !== null) {
		if (on === true) {
			this.highlightSpan.addClass('yellowHighlighter');
		} else {
			this.highlightSpan.removeClass('yellowHighlighter');
		}
	}
}

CdSearchVehicleTypes.prototype.somethingChecked = function( ) {
	var selected = 0;
	var types = [];
	for (var x = 0; x < this.checkboxes.length; ++x) {
		if (this.checkboxes[x].checked) {
			++selected;
			
			var key = this.checkboxes[x].value;
			types.push(key);
		}
	}
	return {'selected': selected, 'types': types};
};

CdSearchVehicleTypes.prototype.addClear = function( ) {
	this.clearDiv = new Element('a', {
		'href': 'javascript:void(0)',
		'html': 'All Types',
		'styles': {'margin-left': '3px'},
		'events': {
			'click': (function() {this.clear();}).bindWithEvent(this)
		}
	});
	
	this.clearDiv.inject(this.span, 'after');
};

CdSearchVehicleTypes.prototype.clear = function( ) {
	for (var x = 0; x < this.checkboxes.length; ++x) {
		this.checkboxes[x].checked = false;
	}
	
	this.hide();
};


function CdFormInputExtender( inputs ) {
	if (typeof inputs !== 'object') {
		inputs = window.document.getElements('input');
	}
	
	inputs.each(function(inp) {
		inp.addEvent('keypress', function( e ) {
			if (e.event.altKey && !e.event.ctrlKey && !e.event.shiftKey) {
				switch (e.code) {
					case 108:			// ALT-L -- lower case
						inp.value = inp.value.toLowerCase();
						break;
					case 117:			// ALT-U -- UPPER CASE
						inp.value = inp.value.toUpperCase();
						break;
					case 119:			// ALT-W -- Word Case
						inp.value = inp.value.capitalize();
						break;
					default:
						return;
				}
				
				// if not default case, stop event
				e.stopPropagation();
			}
		});
	});
	
	$$('.RemoveAfter2').each(function( div ) {
		(function() {div.style.display = 'none';}).delay(2000);
	});
}

// add window 'scroll' event to keep div viewable
function setKeepTop( ) {
	$$('.KeepTop').each(function( div ) {
		div.setAttribute('_y', div.getPosition().y);
		
		window.addEvent('scroll', function( ) {
			div.style.top = (parseInt(div.getAttribute('_y'), 10) + window.getScroll().y) + 'px';
		});
	});
}

// configure links for sample prices
function setEditorSamplePrices( manager ) {
	$$('.FatSamplesEditorLink').each(function( div ) {
		setEditorSamplePricesDiv(manager, div);
	});
}

// configure links for sample prices
function setEditorSamplePricesDiv( manager, div ) {
	// get the encompassing group
	// on multi-load form, there'll be a dividing group in <TR>
	var group = div.getParent('.FatSamplesEditorLinkGroup');
	// if no group, use the form -- when there's one load
	if (group === null) {
		group = div.getParent('form');
	}
	
	// if no form, bail
	if (group === null) {
		return;
	}
	
	// get all components within the group that are needed for sample price. requires class assignments.
	try {
		var cities = group.getElements('.FatCity');
		var states = group.getElements('.FatState');
		var zips = group.getElements('.FatZip');
		var valids = group.getElements('.FatValid');
		
		var load = {
			'oCity': cities[0], 'oState': states[0], 'oZip': zips[0], 'oValid': valids[0],
			'dCity': cities[1], 'dState': states[1], 'dZip': zips[1], 'dValid': valids[1],
			'num_vehicles': group.getElement('.CdNumVehicles'),
			'vehicleTypes': group.getElement('.CdVehicleTypes'),
			'shipMethod': group.getElement('.CdShipMethod'),
			'operable': group.getElement('.CdOperable')
		};
	} catch (e) {
		return;
	}
	
	// set up the div
	div.addClass('mbLink');
	div.rel = 'noDesc,width:750,height:230';
	if (div.title === '') {
		div.title = div.innerHTML;
	}
	
	initIE6Hover(div);
	
	// add click event for showing samples
	div.addEvent('click', (function( e ) {
		var error = '';
		
		var method = load.shipMethod.value;
		if (method === 'Driveaway') {
			error += 'The Sample Prices feature is not supported with "Driveaway" vehicle.<br>';
		}
		
		if (load.oValid.value !== '1' || load.oCity.value === '' || load.dValid.value !== '1' || load.dCity.value === '') {
			error += 'Please enter valid U.S. locations.<br>';
		} else if (isConusState(load.oState.value) === false || isConusState(load.dState.value) === false) { // Ensure Continental US locations.
			error += 'The Sample Prices feature is supported only to Continental U.S. locations.<br>';
		}
		
		if (error !== '') {
			this.href = '/ajax/SamplePrices.php/error/' + escape(error);
		} else {
			var oZip = escape(load.oZip.value);
			var dZip = escape(load.dZip.value);
			var enclosed = method === 'Enclosed' ? '1' : '0';
			var inop = load.operable.value === '0' ? '1' : '0';
			var numVehicles = escape(load.num_vehicles.value);
			var vehicleType = load.vehicleTypes === null ? '+' : escape(load.vehicleTypes.value);
			
			if (oZip === '') {
				oZip = escape(load.oCity.value + ',' + load.oState.value);
			}
			if (dZip === '') {
				dZip = escape(load.dCity.value + ',' + load.dState.value);
			}
			
			this.href = '/ajax/SamplePrices.php/' + oZip + '/' + dZip + '/0/' + enclosed + '/' + inop + '/' + numVehicles + '/' + vehicleType;
		}
	}).bind(div));
}

// Is this a Continental U.S. State?
function isConusState( state ) {
	var ret = false;
	
	switch (state.toUpperCase()) {
		case 'AL':
//		case 'AK': // not Alaska
		case 'AZ':
		case 'AR':
		case 'CA':
		case 'CO':
		case 'CT':
		case 'DE':
		case 'DC':
		case 'FL':
		case 'GA':
//		case 'HI': // not Hawaii
		case 'ID':
		case 'IL':
		case 'IN':
		case 'IA':
		case 'KS':
		case 'KY':
		case 'LA':
		case 'ME':
		case 'MD':
		case 'MA':
		case 'MI':
		case 'MN':
		case 'MS':
		case 'MO':
		case 'MT':
		case 'NE':
		case 'NV':
		case 'NH':
		case 'NJ':
		case 'NM':
		case 'NY':
		case 'NC':
		case 'ND':
		case 'OH':
		case 'OK':
		case 'OR':
		case 'PA':
		case 'RI':
		case 'SC':
		case 'SD':
		case 'TN':
		case 'TX':
		case 'UT':
		case 'VT':
		case 'VA':
		case 'WA':
		case 'WV':
		case 'WI':
		case 'WY':
			ret = true;
			break;
		default:
			break;
	}
	
	return ret;
}

// ------------------------------------------------------------------------------------


/* 
 * Attach calendar object to input field with class "CalendarInput"
 * A single multi-calendar object is not used because calendars
 */
function initCalendar( ) {
	if (typeof Calendar !== 'undefined') {
		$$('.CalendarInput').each(function(div) {
			initCalendarDiv(div);
		});
	}
}

var initCalendarDivId = 10000;
function initCalendarDiv( div ) {
	if (div.id === '' || div.id === undefined) {
		++initCalendarDivId;
		div.id = 'CalendarInput' + initCalendarDivId;
	}
	
	var cal = {};
	cal[div.id] = 'm/d/Y'; // set date display format when filling input field
	
	// allow past dates or allow "today" and beyond
	var direction = div.hasClass('PastOkay') ? 0 : 0.5;
	
	new Calendar(cal, {'direction': direction});
}

/* 
 * Used to attach "today" checkbox to calendar input field. When checked, field is set for today. If field is changed, checkbox is updated: set checked if today.
 */
function TodayCheckboxInit( ) {
	var date = new Date();
	var day = date.getDate(); if (day < 10) { day = '0' + day; }
	var month = date.getMonth() + 1; if (month < 10) { month = '0' + month; }
	var year = date.getFullYear();
	var today = month + '/' + day + '/' + year;
	
	$$('.TodayCheckbox').each(function(div) {
		var dateIn = div.getNext('.CalendarInput');
		dateIn.addEvent('change', function(e) {
			div.checked = dateIn.value === today;
		}, dateIn);
		
		div.addEvent('click', function(e) {
			if (div.checked) {
				dateIn.value = today;
			}
		});
	});
}





// ------------------------------------------------------------------------------------


// on submit, start the validation process -- wait for AJAX to finish then run standard validation
var multiple_started = false;
function startValidatePostMultiple( form ) {
    if (multiple_started) {
        return false;
    }
    multiple_started = true;    
	FatManager.waitForAllLocations(function( fieldsets ) {
		if (validatePostMultiple(fieldsets)) {
			__unsubmitted = false;
			form.submit();
		}
	});
	return false;
}

function validatePostMultiple( fieldsets ) {
	var errors = '';
	
	if (fieldsets.allEmpty === true) {
		errors = '\nEnter locations and other information for one or more listings.';
	} else {
		var listingNum = 0;
		$$('.VehicleListing').each(function(group) {
			if (!group.hasClass('Hide')) {  // skip template
				++listingNum;
				var newErrors = validatePostMultipleLoad(group, fieldsets);
				if (newErrors !== '') {
					errors += '\nListing #' + listingNum + ':\n' + newErrors;
				}
			}
		});
	}
	
	if (errors !== '') {
		alert('Please correct the following errors:\n' + errors);
		multiple_started = false;
		return false;
	}
	
	return true;
}

function validatePostMultipleLoad( group, fieldsets ) {
	var errors = '';
	
	var price = group.getElement('.Price');
	var quickpay = group.getElement('.QuickPay').getElement('input');
	var comchek = group.getElement('.ComChek').getElement('input');
	var cod = group.getElement('.COD');
	var shipdate = group.getElement('.CalendarInput');
	var cod_payment_method = group.getElement('.COD_Payment_Method')
	
	// turn off any existing errors
	price.removeClass('FieldError');
	quickpay.getNext().removeClass('FieldError');
	comchek.getNext().removeClass('FieldError');
	cod.removeClass('FieldError');
	shipdate.removeClass('FieldError');
	
	// get locations for this load
	var locations = group.getElements('.FatCity');
	
	var oId = locations[0].id;
	var dId = locations[1].id;
	
	var orig = fieldsets.fieldsets[oId];
	var dest = fieldsets.fieldsets[dId];
	
	// if no orig/dest then skip load
	if (orig.empty === true && dest.empty === true) {
		return '';
	}
	
	// validate locations
	if (orig.empty === true || orig.valid === false) {
		errors += 'Enter a valid Origination location.\n';
		FatManager.fieldsets[oId].valid.value = '0';
		FatManager.fieldsets[oId].setError();
	}
	if (dest.empty === true || dest.valid === false) {
		errors += 'Enter a valid Destination location.\n';
		FatManager.fieldsets[dId].valid.value = '0';
		FatManager.fieldsets[dId].setError();
	}
	
	// clean up price and make sure it's there
	price.value = price.value.replace(/[,\$ ]/g, '');
	if (!price.value) {
		errors += 'Enter a price to pay carrier.\n';
		price.addClass('FieldError');
	}
	if (price.value.search(/[^0-9\.]/) > -1) {
		errors += 'Price to pay carrier can only be dollars and cents.\n';
		price.addClass('FieldError');
	}
	
	// check quick pay and comchek
	if (quickpay.checked === true && comchek.checked === true) {
		errors += 'You cannot select both Quick Pay and Comchek.\n';
		quickpay.getNext().addClass('FieldError');
		comchek.getNext().addClass('FieldError');
	}
	
	// clean up and check cod
	cod.value = cod.value.replace(/[,\$ ]/g, '');
	if (cod.value.search(/[^0-9\.]/) > -1) {
		errors += 'COD/COP amount can only be dollars and cents.\n';
		cod.addClass('FieldError');
	}
		
	if (parseFloat(cod.value) > 0) {
		if (!cod_payment_method.value) {
			errors += 'Select a COD/COP payment method.\n';
			cod_payment_method.addClass('FieldError');
		}
		else {
			cod_payment_method.removeClass('FieldError');
		}
	}		
	
	// no cod if quickpay or comchek
	if (parseFloat(cod.value) !== 0 && (quickpay.checked === true || comchek.checked === true)) {
		errors += 'Do not enter a COD amount when using Quick Pay or Comchek.\n';
		cod.addClass('FieldError');
	}
	
	// ship today or later
	var date = new Date();
	var entered = Date.parse(shipdate.value);
	
	if (entered - date.getTime() + 86400000 < 0) { // offset to allow any time during "today"
		errors += 'Date Available to Ship must be today or a date after today.\n';
		shipdate.addClass('FieldError');
	}
	
	// validate vehicles
	vErrors = MyCdVehicleListings.listings[oId].validate();
	if (vErrors.length !== 0) {
		errors += vErrors.join('\n') + '\n';
	}
	
	return errors;
}


// ------------------------------------------------------------------------------------


// on submit, start the validation process -- wait for AJAX to finish then run standard validation
var started = false; // make sure they don't just spam submit
function startValidatePostLoad( form ) {
    if (started) {
        return false;
    }
    started = true;
	FatManager.waitForAllLocations(function( fieldsets ) {
		if (validatePostLoad(form, fieldsets)) {
			__unsubmitted = false;
			form.submit();
		}
	});
	return false;
}

function validatePostLoad( form, fieldsets ) {
	var errors = '';
	
	// validate locations
	var vErrors = FatManager.buildFieldsetErrors(fieldsets);
	if (vErrors.length !== 0) {
		errors += vErrors.join('\n') + '\n';
	}
	
	// validate vehicles
	vErrors = MyCdVehicles.validate();
	if (vErrors.length !== 0) {
		errors += vErrors.join('\n') + '\n';
	}
	
	// turn off any existing errors
	$(form.Price).removeClass('FieldError');
	$(form.cod).removeClass('FieldError');
	$(form.quickpay_check).getNext().removeClass('FieldError');
	$(form.comchek_check).getNext().removeClass('FieldError');
	$(form.cod_payment_method).removeClass('FieldError');
	$(form['load[Shipbegindate]']).removeClass('FieldError');
	
	// clean up price and make sure it's there
	form.Price.value = form.Price.value.replace(/[,\$ ]/g, '');
	if (!form.Price.value) {
		errors += 'Enter a price to pay carrier.\n';
		$(form.Price).addClass('FieldError');
	}
	if (form.Price.value.search(/[^0-9\.]/) > -1) {
		errors += 'Price to pay carrier can only be dollars and cents.\n';
		$(form.Price).addClass('FieldError');
	}
	
	// clean up and check cod
	form.cod.value = form.cod.value.replace(/[,\$ ]/g, '');
	if (form.cod.value.search(/[^0-9\.]/) > -1) {
		errors += 'COD/COP amount can only be dollars and cents.\n';
		$(form.cod).addClass('FieldError');
	}
	
	// check quick pay and comchek
	if (form.quickpay_check.checked === true && form.comchek_check.checked === true) {
		errors += 'You cannot select both Quick Pay and Comchek.\n';
		$(form.quickpay_check).getNext().addClass('FieldError');
		$(form.comchek_check).getNext().addClass('FieldError');
	}
	if (parseFloat(form.cod.value) !== 0 && (form.quickpay_check.checked === true || form.comchek_check.checked === true)) {
		errors += 'Do not enter a COD amount when using Quick Pay or Comchek.\n';
		$(form.cod).addClass('FieldError');
	}
	
	if (parseFloat(form.cod.value) !== 0 && (!form.cod_payment_method.value)) {
		errors += 'You must choose your COD/COP payment method.\n';
		$(form.cod_payment_method).addClass('FieldError');		
	}
	
	// either "today" or a date after today
	if (form.today.checked === false) {
		var date = new Date();
		var entered = Date.parse(form['load[Shipbegindate]'].value);
		
		if (entered - date.getTime() < 0) {
			errors += 'Click "Available Today" or set Date Available to Ship after today.\n';
			$(form['load[Shipbegindate]']).addClass('FieldError');
		}
	}
	
	if (errors !== '') {
		alert('Please correct the following errors:\n\n' + errors);
		started = false;
		return false;
	}
	
	return true;
}


// ------------------------------------------------------------------------------------

//function alertCarrierLimit( type, limit, used ) {
//console.log('alertCarrierLimit', type, limit, used);
//	
//	if (used === 0) {
//		used = 'none';
//	} else if (limit <= used) {
//		used = 'ALL';
//	}
//	
//	var title = 'Carrier-Only ' + type.capitalize() + 'ing Limited to ' + limit + ' Vehicles Per Month';
//	var msg = "\
//<b>You have used " + used + " of your " + type + "ing limit of " + limit + " vehicles per month.</b>\
//<br>\
//<br>Your profile indicates that you are a carrier-only. Please be aware that federal regulations require you to have a broker authority and bond to arrange transport for vehicles that you are not buying or selling.\
//<br>\
//<br>To accommodate emergency situations, you may " + type + " up to " + limit + " vehicles each month. If you would like to " + type + " more than " + limit + " vehicles and not see this warning every time, please obtain broker authority and update your CentralDispatch account.\
//<br>\
//<br>You can start your broker application through \
//<a href='http://www.fmcsa.dot.gov/registration-licensing/online-registration/onlineregdescription.htm' target='_blank'>Federal Motor Carrier Safety Administration (FMCSA)</a>. \
//This process typically takes 4-6 weeks. Once completed, contact CentralDispatch to update your account.";
//	
//	$('ymdOpener').addEvent('click', function( e ) {
//		StickyWin.alert(title, msg, {uiOptions: {width: 550}});
//		e.stop();
//	});
//}



// ------------------------------------------------------------------------------------

function mootoolTips( types ) {
	var as = [];
	
	types.each(function(type) {
		$$(type).each(function(div){
			if (div.getAttribute('title')) { as.push(div); }
		});
	});
	
	new Tips(as, {maxOpacity: 0.9, maxTitleChars: 25, className: 'MooTip'});
}

// ------------------------------------------------------------------------------------

// IE6 hover on non-link items -- show pointer cursor
var IsIe6Browser = navigator.userAgent.search(/MSIE 6\./) !== -1; // determine whether IE6
function initIE6Hover( divs ) {
	// get divs to process
	if (divs === undefined || !divs) { 			// if not passed, search for IE6Hover class
		divs = $$('.IE6Hover');
	} else if (divs.each === undefined) { // if single element, make it an array
		divs = [divs];
	}
	
	divs.each(function(div) {
		div.removeClass('IE6Hover'); // prevent double-execution
		
		if (IsIe6Browser) {	// add pointer on/off events
			div.addEvent('mouseover', function() {
				div.style.cursor = 'pointer';
			});
			div.addEvent('mouseout', function() {
				div.style.cursor = '';
			});
		}
	});
}
