////////////////////////////////////////////////////////////
///////                                            /////////
///////   QUASK FORM SCRIPT - (C) 2005 Quask Ltd   /////////
///////                                            /////////
////////////////////////////////////////////////////////////


//=========================================================
//=============== DYNAMIC FORM DATA =======================
//=========================================================


//---------------------------------------------------------
//------------------------ Form  --------------------------
//---------------------------------------------------------


f_appversion = "1.0.175.0";				//DLL Version
f_title = "Ley de Dependencia";					//Title of form
f_guid = "08ACB10EFB7E47EC8066722579783064";					//GUID of form
f_version = "xxx-xxxxxx";				//Version of form
f_tag = "";					//Form Tag
f_preview = false;					//Preview Mode?
f_unbranded = true;					//Unbranded?
f_trialversion = false;				//Trial Version?
f_singleresponse = false;				//Is it a single-response form?
f_readonly = false;					//Is the whole form read-only?
f_noscripts = false;					//Don't allow any script to run (when viewing data in FA)
f_allowpreload = true;				//Not in Presto
f_forcefocus = true;					//Make sure page scrolls down/up so that the page/object that is displayed is visible (IE only)
f_aftersend = "0";				//0..default, 1...Fill again, 2..Close Window, 9..Demo Mode (Close upon Send)
f_hourglass = 6;					//If >0, use hourglass between pages
f_requirespopup = false;				//If true, needs be able to create pop-up windows (GetURL(), Upload)
f_splitpage = false;					//If true, every page is on a new HTML page
f_encryption = false;					//If true, preload-data and submit data is encrypted

f_self_url = "formrender.asp";				//Page that renders form ie. myself (for email embedded success url)
f_data_url = "<QFS_URLBASE/>public.asmx/submit";				//URL for sending data to
f_src_url = "<QFS_URLBASE/>dhtmlform/08ACB10EFB7E47EC8066722579783064.xml";				//XML source of this form (for QPD viewer)
f_success_url = "";			//URL that is displayed when data sending was successful ("" if this page)
f_failure_url = "";			//URL that is displayed when data sending failed ("" if this page)
f_upload_url = "";				//URL for file uploading
f_servercomm_url = "<QFS_URLBASE/>svrcomm.aspx";			//URL for server communication
f_sendformmanager = false;			//Sends data to FormManager instead of POST
f_unload_url = "<QFS_URLBASE/>svrcomm.aspx?qf_event=close&instid=<QFS_INSTID/>";				//URL that is called window OnUnload event
f_keepalive_url = "";			//URL that is triggered are regular intervals to inform FormServer that the form is still "alive"
f_keepalive_mins = 15;				//Number minutes of the interval
f_initial_workflowstage = "New";	//Default value for this SystemProperty
f_intitial_workflowlevel = "0";	//Default value for this SystemProperty

f_events = ["101", "12", "13"];						//OnLoad, OnSend, OnReset
f_page_w = 950;						//Width of page
f_page_h = 600;						//Height of page
f_page_start = 0;					//First page to be shown

f_loading_image_id = "q_loadpic";		//<img id=...> of loading image in html page

f_skin = true;					//Has skin or not
f_skin_w = 20;					//Width of skin-element (Must be 0 if no skin)
f_skin_h = 20;					//Width of skin-element (Must be 0 if no skin)
f_skin_btns = 0;				//0=No buttons, 1=Send/Reset only, 2=Page Navi only, 3=All on one line, 4=All on two lines
f_skin_defaultcolor = "ffffff";	//Color that is drawn in the middle (Sending...)

//Fonts
f_fonts = [
	"10pt|Arial|0",
	"15pt|Arial|0",
	"12pt|Arial|0",
	"12pt|Arial|1",
	"11pt|Arial|0",
	"10pt|Arial|2",
	"10pt|Arial|3",
	"10pt|Arial|1",
	"9pt|Arial|0",
	"11pt|Arial|1",
	"11pt|Arial|3",
	"9pt|Arial|1",
	"13pt|Arial|1",
	"16pt|Arial|0",
	"20pt|Arial|1",
	"16pt|Arial|1"
	];


//---------------------------------------------------------
//------------------------ Pages --------------------------
//---------------------------------------------------------


f_page_def = [
	["dfdfdf", "Page 5", "113", 0, 0],
	["dfdfdf", "Page 1", "1", 0, 0],
	["dfdfdf", "Page 2", "19", 0, 0],
	["dfdfdf", "Page 3", "37", 0, 0],
	["dfdfdf", "Page 4", "78", 0, 0]
	];


//---------------------------------------------------------
//--------------------- Controls  -------------------------
//---------------------------------------------------------


//Bass class: type, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, font
f_controls_def = [

	//------------------ Labels  -----------------------

	//---- Page 1 ("Page 1") ----

	//Text Label ("Label 2")
	[1, "5", "TAG_5", 0, 1, 1, 32, 56, 329, 40, 0, 0, 0, "", "000000", 1, 3,
		0, 5, 0],

	//Text Label ("q1 indique")
	[1, "7", "TAG_7", 0, 1, 2, 207, 96, 160, 22, 0, 0, 0, "", "000000", 3, 6,
		1, 5, 0],

	//Text Label ("Label 4")
	[1, "9", "TAG_9", 0, 1, 3, 33, 172, 287, 72, 0, 0, 0, "", "000000", 5, 3,
		2, 5, 0],

	//Text Label ("Label 12")
	[1, "57", "TAG_5", 0, 1, 6, 28, 334, 324, 74, 0, 0, 0, "", "000000", 9, 3,
		3, 5, 0],

	//Picture Label ("Shape 1")
	[6, "75", "TAG_75", 0, 1, 7, 24, 328, 908, 84, 0, 0, 0, "dfdfdf", "dfdfdf", 10, 8,
		7, 908, 84, 0],

	//Text Label ("Label 7")
	[1, "109", "TAG_109", 0, 1, 7, 396, 568, 96, 32, 0, 0, 0, "", "000000", 11, 3,
		4, 5, 0],


	//---- Page 2 ("Page 2") ----

	//Text Label ("Label 10")
	[1, "24", "TAG_9", 0, 2, 2, 15, 284, 405, 88, 0, 0, 0, "", "000000", 3, 3,
		5, 5, 0],

	//Text Label ("Label 11")
	[1, "25", "TAG_11", 0, 2, 2, 462, 266, 397, 21, 0, 0, 0, "", "000000", 4, 10,
		6, 5, 0],

	//Text Label ("Q5 indique")
	[1, "27", "TAG_7", 0, 2, 3, 288, 436, 160, 22, 0, 0, 0, "", "000000", 6, 6,
		7, 5, 0],

	//Text Label ("Label 16")
	[1, "34", "TAG_34", 0, 2, 6, 506, 388, 20, 15, 0, 0, 0, "", "000000", 8, 11,
		8, 5, 0],

	//Text Label ("Label 9")
	[1, "59", "TAG_12", 0, 2, 7, 15, 73, 424, 116, 0, 0, 0, "", "000000", 9, 3,
		9, 5, 0],

	//Text Label ("Label 17")
	[1, "61", "TAG_14", 0, 2, 8, 462, 75, 219, 25, 0, 0, 0, "", "000000", 11, 9,
		10, 5, 0],

	//Text Label ("Label 27")
	[1, "62", "TAG_15", 0, 2, 8, 462, 119, 264, 40, 0, 0, 0, "", "000000", 12, 9,
		11, 5, 0],

	//Text Label ("Label 6")
	[1, "108", "TAG_108", 0, 2, 9, 432, 568, 96, 32, 0, 0, 0, "", "000000", 14, 3,
		12, 5, 0],


	//---- Page 3 ("Page 3") ----

	//Text Label ("Label 18")
	[1, "41", "TAG_41", 0, 3, 1, 19, 346, 360, 74, 0, 0, 0, "", "000000", 1, 3,
		13, 5, 0],

	//Text Label ("Label 19")
	[1, "43", "TAG_5", 0, 3, 2, 19, 462, 360, 44, 0, 0, 0, "", "000000", 3, 3,
		14, 5, 0],

	//Text Label ("Label 20")
	[1, "99", "TAG_5", 0, 3, 3, 19, 50, 408, 52, 0, 0, 0, "", "000000", 7, 3,
		15, 5, 0],

	//Text Label ("Label 21")
	[1, "102", "TAG_32", 0, 3, 5, 19, 100, 388, 74, 0, 0, 0, "", "000000", 10, 3,
		16, 5, 0],

	//Text Label ("Label 22")
	[1, "103", "TAG_33", 0, 3, 5, 430, 95, 397, 21, 0, 0, 0, "", "000000", 11, 10,
		6, 5, 0],

	//Text Label ("Q7 indique")
	[1, "104", "TAG_7", 0, 3, 5, 298, 279, 160, 22, 0, 0, 0, "", "000000", 12, 6,
		7, 5, 0],

	//Text Label ("Label 5")
	[1, "107", "TAG_107", 0, 3, 6, 431, 568, 96, 32, 0, 0, 0, "", "000000", 14, 3,
		17, 5, 0],


	//---- Page 4 ("Page 4") ----

	//Text Label ("Label 33")
	[1, "86", "TAG_45", 0, 4, 3, 28, 164, 388, 24, 0, 0, 0, "", "000000", 3, 3,
		18, 5, 0],

	//Text Label ("Label 37")
	[1, "92", "TAG_56", 0, 4, 5, 156, 328, 592, 48, 0, 0, 0, "0000ff", "ffff00", 4, 14,
		19, 15, 0],

	//Text Label ("Label 38")
	[1, "93", "TAG_64", 0, 4, 5, 28, 64, 320, 28, 0, 0, 0, "c0c0c0", "000000", 5, 3,
		20, 5, 0],

	//Text Label ("Label 3")
	[1, "106", "TAG_106", 0, 4, 7, 384, 568, 96, 32, 0, 0, 0, "", "000000", 7, 3,
		21, 5, 0],

	//Text Label ("Label 40")
	[1, "120", "TAG_120", 0, 4, 7, 28, 240, 440, 28, 0, 0, 0, "", "000000", 8, 3,
		22, 5, 0],


	//---- Page 0 ("Page 5") ----

	//Text Label ("Label 13")
	[1, "114", "TAG_114", 0, 0, 1, 32, 44, 891, 228, 0, 0, 0, "c0c0c0", "000000", 1, 1,
		23, 5, 0],

	//Text Label ("Quest Edad1")
	[1, "115", "TAG_111", 0, 0, 1, 36, 308, 168, 24, 0, 0, 0, "", "000000", 2, 3,
		24, 5, 0],

	//Text Label ("Label 14")
	[1, "117", "TAG_117", 0, 0, 2, 416, 568, 96, 32, 0, 0, 0, "", "000000", 4, 3,
		25, 5, 0],


	//------------- User Drawn Controls  ---------------

	//---- Page 1 ("Page 1") ----

	//Tickbox Group ("Q2")
	[7, "10", "TAG_10", 0, 1, 3, 372, 168, 550, 85, 0, 0, 0, "e0e0e0", "000000", 6, 0,
		0, 0, 0, 16, 8, 1, 13, 0,
		[
			[0, 0, 529, 16, 27, 26, 0],
			[0, 20, 550, 16, 29, 28, 0],
			[0, 40, 460, 16, 31, 30, 0],
			[0, 60, 386, 16, 33, 32, 0]
		],
		["", "137"]],


	//---- Page 2 ("Page 2") ----

	//Tickbox Group ("Q5")
	[7, "26", "TAG_26", 0, 2, 2, 460, 288, 302, 140, 0, 0, 0, "dfdfdf", "000000", 5, 8,
		1, 0, 0, 16, 8, 1, 13, 0,
		[
			[0, 0, 133, 16, 34, 26, 0],
			[0, 20, 168, 16, 35, 28, 0],
			[0, 40, 135, 16, 36, 30, 0],
			[0, 60, 103, 16, 37, 32, 0],
			[0, 80, 133, 16, 39, 38, 0],
			[0, 100, 257, 16, 41, 40, 0],
			[0, 120, 48, 16, 43, 42, 0]
		],
		["", "115"]],


	//---- Page 3 ("Page 3") ----

	//Tickbox Group ("Q7")
	[7, "101", "TAG_31", 0, 3, 4, 430, 118, 456, 165, 0, 0, 0, "dfdfdf", "000000", 9, 8,
		1, 0, 0, 16, 8, 1, 13, 0,
		[
			[0, 0, 311, 16, 44, 26, 0],
			[0, 20, 344, 16, 45, 28, 0],
			[0, 40, 235, 16, 46, 30, 0],
			[0, 60, 408, 16, 47, 32, 0],
			[0, 80, 347, 16, 48, 38, 0],
			[0, 100, 327, 16, 49, 40, 0],
			[0, 120, 456, 16, 50, 42, 0],
			[0, 140, 51, 16, 52, 51, 0]
		],
		["", "158"]],


	//---- Page 4 ("Page 4") ----


	//---- Page 0 ("Page 5") ----


	//---------------- All others  ---------------------

	//---- Page 1 ("Page 1") ----

	//Drop-Down Selection ("Q1")
	[9, "6", "TAG_6", 0, 1, 1, 371, 60, 399, 22, 0, 0, 0, "ffffff", "000000", 2, 0,
		[53, 54, 55, 43],
		[26, 28, 30, 32],
		-1, 0, ["", "105"]],

	//Text Input ("Q1 other")
	[2, "8", "TAG_8", 0, 1, 2, 371, 96, 399, 22, 0, 0, 0, "ffffff", "000000", 4, 0,
		0, 128, 0, 56, 56, 0],

	//Button ("Action Button 2")
	[12, "18", "TAG_18", 0, 1, 6, 816, 568, 133, 30, 0, 0, 0, "c0ffff", "000000", 7, 0,
		0, 57, 8, "", 0],

	//Drop-Down Selection ("Q3")
	[9, "58", "TAG_6", 0, 1, 6, 368, 336, 399, 22, 0, 0, 0, "ffffff", "000000", 8, 0,
		[58, 59, 60, 61],
		[26, 28, 30, 32],
		-1, 0, 0],

	//Button ("Action Button 9")
	[12, "119", "TAG_119", 0, 1, 7, 0, 574, 148, 26, 0, 0, 0, "c0ffff", "000000", 12, 0,
		0, 62, 9, "", 0],


	//---- Page 2 ("Page 2") ----

	//Button ("Action Button 1")
	[12, "20", "TAG_20", 0, 2, 1, 0, 572, 148, 26, 0, 0, 0, "c0ffff", "000000", 1, 0,
		0, 62, 9, "", 0],

	//Button ("Action Button 3")
	[12, "21", "TAG_21", 0, 2, 1, 824, 570, 126, 30, 0, 0, 0, "c0ffff", "000000", 2, 0,
		0, 57, 8, "", 0],

	//Text Input ("Q5 other")
	[2, "28", "TAG_8", 0, 2, 3, 460, 432, 399, 22, 0, 0, 0, "ffffff", "000000", 7, 0,
		0, 128, 0, 56, 56, 0],

	//Date-Time Input ("Q4-1")
	[10, "60", "TAG_13", 0, 2, 7, 727, 75, 143, 22, 0, 0, 0, "ffffff", "000000", 10, 0,
		2, 3, 0, 0, "", 2007, 2009, 0, 0, null,  0],

	//Date-Time Input ("Q4-2")
	[10, "63", "TAG_16", 0, 2, 8, 727, 119, 143, 22, 0, 0, 0, "ffffff", "000000", 13, 0,
		2, 3, 0, 0, "", 2007, 2009, 0, 0, null,  0],


	//---- Page 3 ("Page 3") ----

	//Text Input ("Q8")
	[2, "42", "TAG_42", 0, 3, 1, 430, 346, 467, 100, 0, 0, 0, "ffffff", "000000", 2, 8,
		1, 250, 0, 56, 56, 0],

	//Drop-Down Selection ("Q9")
	[9, "44", "TAG_6", 0, 3, 2, 430, 464, 100, 22, 0, 0, 0, "ffffff", "000000", 4, 0,
		[63, 64],
		[26, 28],
		-1, 0, 0],

	//Button ("Action Button 4")
	[12, "97", "TAG_20", 0, 3, 3, 0, 572, 148, 26, 0, 0, 0, "c0ffff", "000000", 5, 0,
		0, 62, 6, "", ["", "180"]],

	//Button ("Action Button 5")
	[12, "98", "TAG_21", 0, 3, 3, 824, 570, 126, 30, 0, 0, 0, "c0ffff", "000000", 6, 0,
		0, 57, 8, "", 0],

	//Drop-Down Selection ("Q6")
	[9, "100", "TAG_6", 0, 3, 3, 430, 47, 399, 22, 0, 0, 0, "ffffff", "000000", 8, 0,
		[65, 66, 67, 68],
		[26, 28, 30, 32],
		-1, 0, 0],

	//Text Input ("Q7 other")
	[2, "105", "TAG_8", 0, 3, 5, 430, 278, 378, 22, 0, 0, 0, "ffffff", "000000", 13, 0,
		0, 128, 0, 56, 56, 0],


	//---- Page 4 ("Page 4") ----

	//Button ("Action Button 6")
	[12, "79", "TAG_20", 0, 4, 1, 2, 572, 144, 26, 0, 0, 0, "c0ffff", "000000", 1, 0,
		0, 62, 9, "", 0],

	//Button ("Action Button 7")
	[12, "80", "TAG_21", 0, 4, 1, 752, 520, 198, 80, 0, 0, 0, "ffffc0", "ff0000", 2, 13,
		0, 69, 1, "", 0],

	//Drop-Down Selection ("Ciudad")
	[9, "96", "TAG_77", 0, 4, 6, 412, 165, 360, 21, 0, 0, 0, "ffffff", "000000", 6, 8,
		[70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88],
		[26, 28, 30, 32, 38, 40, 42, 51, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99],
		-1, 0, 0],

	//Numeric Input ("Num input EDAD 5/5")
	[3, "121", "TAG_121", 0, 4, 7, 456, 240, 48, 22, 0, 0, 0, "ffffff", "000000", 9, 8,
		2, 0, 56, 0],


	//---- Page 0 ("Page 5") ----

	//Numeric Input ("Num Input EDAD1")
	[3, "116", "TAG_112", 0, 0, 1, 196, 308, 40, 22, 0, 0, 0, "ffffff", "000000", 3, 8,
		2, 0, 56, 0],

	//Button ("Action Button 8")
	[12, "118", "TAG_118", 0, 0, 2, 817, 570, 133, 30, 0, 0, 0, "c0ffff", "000000", 5, 0,
		0, 57, 6, "", ["", "235"]],

	null]; //Last one is empty



//---------------------------------------------------------
//--------------------- Resources -------------------------
//---------------------------------------------------------


//Resources 0..gif, 1..jpg, 2..wav, 3..mid, 4..mp3
f_resources_path = "<QFS_URLBASE/>dhtmlform/08ACB10EFB7E47EC8066722579783064_gfx/";
f_resources_type = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

//String Table
f_strings = [
	"&#191;Cu&#225;l es su relaci&#243;n con este tema?",
	"Ind&#237;quela, por favor:",
	"Respecto al reconocimiento de la situaci&#243;n de dependencia, &#191;ha sido ya valorado seg&#250;n la nueva Ley?: ",
	"Si corresponde, &#191;cu&#225;l es su grado de dependencia seg&#250;n el baremo que se aplica con la nueva Ley? ",
	"P&#225;gina 2/5",
	"En caso de que proceda, indique por favor, qu&#233; prestaciones est&#225; recibiendo como resultado de la valoraci&#243;n gracias a la nueva Ley",
	"puede marcar m&#225;s de una respuesta",
	"Indique, por favor:",
	"no",
	"Posiblemente haya pasado tiempo entre las fechas en que pidi&#243; cita para la valoraci&#243;n, el momento en el que se la han hecho y la fecha en la que le han comunicado su grado de dependencia. Indique por favor, cu&#225;les fueron esas fechas, de forma aproximada",
	"Fecha de solicitud: ",
	"Fecha de notificaci&#243;n del grado de dependencia (si procede): ",
	"P&#225;gina 3/5",
	"Si UD. tiene alguna otra queja u observaci&#243;n que hacer no recogida en el cuestionario, puede escribirla a continuaci&#243;n: ",
	"&#191;Es usted socio de la OCU?",
	"&#191;Est&#225; percibiendo otras ayudas no derivadas de la actual Ley de Dependencia? ",
	"&#191;Cu&#225;l es su principal denuncia u observaci&#243;n?",
	"P&#225;gina 4/5",
	"Comunidad/Ciudad Aut&#243;noma (en la que reside):",
	"Much&#237;simas gracias por su colaboraci&#243;n.",
	"Datos de la persona dependiente.",
	"P&#225;gina 5/5",
	"Edad (si a&#250;n no ha cumplido un a&#241;o de edad, anote 0):",
	"Desde la OCU deseamos contribuir a que la Ley de la Promoci&#243;n de la Autonom&#237;a Personal y Atenci&#243;n a la Dependencia llegue a todos los afectados. Por ello deseamos conocer la experiencia tanto de las personas con distinto grado de dependencia, como de los encargados de su cuidado.<br><br>Le agradecemos que responda a este cuestionario: hacerlo apenas le llevar&#225; unos minutos. <br><br>Es importante que sepa que este cuestionario lo puede rellenar una persona que no se encuentre en una situaci&#243;n de dependencia pero para ello es necesario que usted haya cumplido los 18 a&#241;os de edad.<br>",
	"&#191;Cu&#225;l es su edad? &nbsp;",
	"P&#225;gina 1/5",
	"1",
	"S&#237;, ya ha sido valorado y tiene reconocido el grado de dependencia seg&#250;n la nueva Ley ",
	"2",
	"S&#237;, ya ha sido valorado pero est&#225; en espera de que le comuniquen el grado de dependencia",
	"3",
	"No, a pesar de solicitar cita para que lo valoren, a&#250;n est&#225; en lista de espera",
	"4",
	"No, a&#250;n no ha solicitado que valoren su grado de dependencia ",
	"Atenci&#243;n residencial",
	"Estancia en centros de d&#237;a",
	"Servicios a domicilio",
	"Teleasistencia",
	"5",
	"Ayudas econ&#243;micas",
	"6",
	"A&#250;n no est&#225; recibiendo ninguna prestaci&#243;n",
	"7",
	"Otra.",
	"El retraso en la valoraci&#243;n del grado de dependencia",
	"El desacuerdo con la valoraci&#243;n del grado de dependencia",
	"El retraso para recibir las prestaciones",
	"La incompatibilidad con otras prestaciones (anteriores o simult&#225;neas)",
	"No tiene plaza en las residencias o centros sociosanitarios",
	"No tiene apoyo de profesionales o servicios adecuados",
	"No tiene observaci&#243;n que hacer. Las prestaciones recibidas son satisfactorias.",
	"8",
	"Otra. ",
	"Tiene una situaci&#243;n de dependencia",
	"Es cuidador o familiar de una persona con dependencia",
	"Es personal sociosanitario",
	"",
	"Siguiente",
	"Gran dependencia",
	"Dependencia Severa Grado II",
	"Dependencia Severa Grado I",
	"Dependencias moderadas",
	"Atrás",
	"S&#237;",
	"No",
	"S&#237; y por lo que sabe son complementarias a las de la nueva Ley",
	"S&#237;, pero no son complementarias a las de la nueva ley",
	"S&#237;, aunque desconoce si son complementarias o no",
	"No, no est&#225; percibiendo otras ayudas",
	"Enviar\ncuestionario",
	"Andaluc&#237;a",
	"Arag&#243;n",
	"Asturias",
	"Baleares",
	"Canarias",
	"Cantabria",
	"Castilla-La Mancha",
	"Castilla y Le&#243;n",
	"Catalu&#241;a",
	"Comunidad Valenciana",
	"Extremadura",
	"Galicia",
	"La Rioja",
	"Madrid",
	"Murcia",
	"Navarra",
	"Pa&#237;s Vasco",
	"Ceuta",
	"Melilla",
	"9",
	"10",
	"11",
	"12",
	"13",
	"14",
	"15",
	"16",
	"17",
	"18",
	"19"
	];


//---------------------------------------------------------
//------------------- User Scripts ------------------------
//---------------------------------------------------------


function q_RunScript2(script_id, current_obj, current_page, params)
{
	switch(script_id)
	{
		case "105":
		{
if(q_GetControlByID("6").GetState(4) == true) {q_GetControlByID("7").SetMode(272); q_GetControlByID("8").SetMode(272);}
 else {q_GetControlByID("7").SetMode(288); q_GetControlByID("8").SetMode(288);q_GetControlByID("8").SetValue(""); };
		};
		break;

		case "115":
		{
if(q_GetControlByID("26").GetState(7) == true) {q_GetControlByID("27").SetMode(272); q_GetControlByID("28").SetMode(272);}
 else {q_GetControlByID("27").SetMode(288); q_GetControlByID("28").SetMode(288);q_GetControlByID("28").SetValue(""); };
		};
		break;

		case "137":
		{
if(q_GetControlByID("10").GetState(1) == true) {q_GetControlByID("75").SetMode(288); q_GetControlByID("58").SetMode(272);}
 else if((q_GetControlByID("10").GetState(2) == true | q_GetControlByID("10").GetState(3) == true)) {q_GetControlByID("58").SetMode(288); q_GetControlByID("75").SetMode(272);q_NextPage();q_GetControlByID("58").SetValue(""); }
 else if(q_GetControlByID("10").GetState(4) == true) {q_GetControlByID("58").SetMode(272); q_GetControlByID("75").SetMode(272);q_GetPageByID("37").GoTo();q_GetControlByID("58").SetValue(""); };
		};
		break;

		case "158":
		{
if(q_GetControlByID("101").GetState(8) == true) {q_GetControlByID("104").SetMode(272); q_GetControlByID("105").SetMode(272);}
 else {q_GetControlByID("105").SetMode(288); q_GetControlByID("104").SetMode(288);q_GetControlByID("105").SetValue(""); };
		};
		break;

		case "180":
		{
if(q_GetControlByID("10").GetState(4) == true) {q_GetControlByID("75").SetMode(272); q_GetControlByID("58").SetMode(288);q_GetPageByID("1").GoTo();}
 else {q_PrevPage();};
		};
		break;

		case "235":
		{
if(q_GetControlByID("116").GetValue() < 18) {q_ShowMessage("Lo siento, usted debe haber cumplido la mayoría de edad para responder a este cuestionario.");}
 else {q_NextPage();};
		};
		break;

		case "13":
		{

		};
		break;

		case "12":
		{

		};
		break;

		case "101":
		{
q_GetControlByID("7").SetMode(288); q_GetControlByID("8").SetMode(288); q_GetControlByID("27").SetMode(288); q_GetControlByID("28").SetMode(288); q_GetControlByID("104").SetMode(288); q_GetControlByID("105").SetMode(288); q_GetControlByID("58").SetMode(288);
		};
		break;

	};
}



//=========================================================
//======================= TEXTS ===========================
//=========================================================


var q_Texts = [
			"`<obppp705:09K`<b",
			"`<ob9:/Q~'95(9,N`<b",
			"`<ob}:925=X~705:09K~=*=Z`<b",
			"`<obp*09K~%22)8++9;;)K~=*=Z`<b",
			"`<obp9;0/~05~:92258~9<~%20/~0=;~1,/8~+56J`<b",
			":::::",
			"p=*=:~96*~:09K~)/%~9,/89<~0/5*+9)-~+56*~,9'+0=~9+=92N\np:9,9'+0=~099<~*/0~+=6~0/5*+9)-~%,/*=:0=1~]",
			"_1,/8~+56*~05~:2958~6;=9~*9+9,~/*~*0='~)/%~9,)+~)/%~9,]",
			"",
			"p0/5*;0)8~*05,.~+w,9+'/,\\~,)/%~705+)~+97=.~92705+~*05,.~0=;~)/%~r%29(5*=0,9*2]\n\np1,/8~9*92.1/;~96*~*05,.~/*~7/2=5:~6;=9~0/~w*05,Nw~++9,N\n\np1,/8~+56*~05~97=.~6;=9~,/8~7/2=5:~*05,N~=~6*5'~:9*09+9,.~9<~225'~)/E",
			"p705*05,.~:96+5058~+=6~97=.~+56*~,9*8=~05=7=~*05,N~++9,.~:0=~+97=.~,96*/~96*~/*~9*=75(=P\n\np:9*05,.~9<~225'~97=.~*09,,);~96*~%20O\n\np915*~96*~*=~97=.~90/~705*05,.~+*,/..)+~%20/~,9+'/,<~,)/E",
			"`=ob3+=)M`l2-?*+a++=2;~30=2<?a*97,=*~|1,/8o1/;p3+=)-p'''ood.**6|a89,6~=b~%<~:9,9'/.",
			"'/:05G~9+/2[",
			"05=7=~05~225X",
			"9)05*0/[",
			"ppp+25=*9Z",
			"p'/:05'~'90~=~05~:9%=2.+5:~9<~225'~0/5*=1,580/[`,<b`,<b`<obppp705:09K`<b",
			"p++9,::=~25=19~:52=(~=~,9*0Y",
			"pRLI~:52=(~=~,9*0Y",
			"",
			""
	];



//=========================================================
//============ CROSS-BROWSER HANDLING LIBRARY =============
//=========================================================


//Browser Flags
var q_bIE = false; 
var q_bDOM2 = false; 
var q_bMac = false; 
var q_bMoz15 = false;
var q_bFirefox = false; 
var q_bFirefox2 = false;

if(document.all) q_bIE = true;
else if(document.getElementById) q_bDOM2 = true;
if(navigator.appVersion.indexOf("Mac")>=0) q_bMac = true;
if(navigator.userAgent.indexOf("Mozilla")>=0 && (navigator.userAgent.indexOf("1.5")>=0 || navigator.userAgent.indexOf("1.4"))>=0) q_bMoz15 = true;
if(navigator.userAgent.indexOf("Firefox")>=0) q_bFirefox = true;
if(navigator.userAgent.indexOf("Firefox/2")>=0) q_bFirefox2 = true;

if((!q_bDOM2 && !q_bIE)									        //Unidentified browser
	|| (q_bIE && navigator.appVersion.indexOf("MSIE 4.")!=-1))	//IE4 not supported (yet)
{	
	alert("Your browser version cannot render the form on this page.\nPlease upgrade your browser.");
}
if(q_bDOM2 && navigator.userAgent.indexOf("Netscape6")!=-1)
{
	//N6 recommend update to N7
	alert("We recommend that you upgrade your browser to the latest version in order to render the form on this page.");
}


//--- Layor-Stylesheet Helpers ---

function q_Style(id)
{
	if(q_bIE) return document.all[id].style;
	if(q_bDOM2) return document.getElementById(id).style;
}

function q_GetLeft(id)
{
	if(q_bIE) return q_Style(id).pixelLeft;
	if(q_bDOM2) {l=parseInt(q_Style(id).left); if(l*0!=0)l=0; return l;};
}

function q_SetLeft(id, x)
{
	if(q_bIE) q_Style(id).pixelLeft = x;
	if(q_bDOM2) q_Style(id).left = x + "px";
}

function q_GetTop(id)
{
	if(q_bIE) return q_Style(id).pixelTop;
	if(q_bDOM2) {t=parseInt(q_Style(id).top); if(t*0!=0)t=0; return t;};
}

function q_SetTop(id, y)
{
	if(q_bIE) q_Style(id).pixelTop = y;
	if(q_bDOM2) q_Style(id).top = y+"px";
}

function q_SetHeight(id, y)
{
	if(q_bIE) q_Style(id).pixelHeight = y;
	if(q_bDOM2) q_Style(id).height = y+"px";
}

function q_SetVisible(id, v)
{
	q_Style(id).visibility = v?'visible':'hidden';
}

function q_SetBackCol(id,c)
{
	q_Style(id).backgroundColor = c;
}

function q_SetColor(id,c)
{
	q_Style(id).color = c;
}

function q_SetZOrder(id,z)
{
	q_Style(id).zIndex = z;
}

function q_SetBorder(id, s, c)
{
	q_Style(id).border = s +"px solid #"+c;
}

function q_GetImage(id, p)
{
    return document.images[p];
}

function q_SetElementBackCol(e, c) //Set color of e.g. <input type=text> element
{
	e.style.backgroundColor=c;
}

function q_SetTransparency(id, v) //0 to 100
{
	if(q_bIE)
	{
		if(v>=0 && v<100)document.all[id].style.filter = "alpha(opacity="+v+")";
		else document.all[id].style.filter = "alpha(enabled=false)";
	}
//	if(q_bDOM2) q_Style(id).MozOpacity=v/100;
}

function q_SetHTML(id, text)
{
	if(q_bIE) document.all[id].innerHTML = text;
	if(q_bDOM2) document.getElementById(id).innerHTML = text;
}

function q_GetBrowserWidth()
{
    return document.body.clientWidth;
}

function q_GetBrowserHeight()
{
	return document.body.clientHeight;
}

function q_PreLoadSound(i)
{
	if(q_bIE) document.writeln('<embed name=q_snd_'+i+' autostart=false autoplay=false src="'+f_resources[i].src+'" hidden=true></embed>');
}

function q_PlaySound(i, loop)
{
	if(q_bIE)
	{
		if(loop)document.all['q_snd_loop'].src=f_resources[i].src;
		else document.all['q_snd_noloop'].src=f_resources[i].src;
	}
	if(q_bDOM2)
		q_OpenWindow(f_resources[i].src, 200, 30);
}

function q_SetHourglass(b)
{
	if(q_bIE) document.body.style.cursor=b?'wait':'default';
}

function q_GetButtonHeight(h)
{
	return h-((q_bMac&&q_bIE)?5:0);
}

function q_GetButtonWidth(w)
{
	return w-((q_bMac&&q_bIE)?10:0);
}

function q_GetControlHeight(h)
{
	return h-((q_bMac&&q_bIE)?4:0);
}

function q_GetControlWidth(w)
{
	return w-((q_bMac&&q_bIE)?4:0);
}

function q_GetComboBoxHeight(h)
{
	return h-((q_bMac&&q_bIE)?4:0)-((q_bFirefox||q_bDOM2)?2:0);
}

function q_SupportsMultipagePrinting()
{
	return q_bIE; //IE only
}

function q_GetCaretPos(e)
{
	//Mozilla/Firefox
	if(e.selectionStart) return e.selectionStart;
	
	//IE
	if(e.createTextRange)
	{
		var c = document.selection.createRange(),
			p=0,
			t = e.createTextRange();

		if(t)
		{
			while(c.compareEndPoints("StartToStart", t) > 0)
			{
				t.moveStart("character", 1);
				p++;
			}
			return p;
		}
	}

	//Not supported
	return -1;
}

function q_SetCaretPos(e, p)
{
	//Mozilla/Firefox
	if(e.setSelectionRange) e.setSelectionRange(p, p);
	
	//IE
	else if(e.createTextRange)
	{
		var r = e.createTextRange();
		r.collapse(true);
		r.moveEnd("character", p);
		r.moveStart("character", p);
		r.select();
	}
}


//--- Event Helpers ---

function q_CaptureEvents()
{
	if(q_bDOM2) document.captureEvents(Event.MOUSEDOWN|Event.MOUSEMOVE|Event.MOUSEUP);
}

function q_GetEventTarget(e)
{
	if(q_bIE) return event.srcElement;
	if(q_bDOM2) return e.target;
}

function q_GetEventKey(e)
{
	if(q_bIE) return event.keyCode;
	if(q_bDOM2) return e.which;
}

function q_GetEventX(e)
{
	if(q_bIE) return document.body.scrollLeft+event.clientX;
	if(q_bDOM2) return e.pageX;
}

function q_GetEventY(e)
{
	if(q_bIE) return document.body.scrollTop+event.clientY;
	if(q_bDOM2) return e.pageY;
}

function q_ScrollIn(x,y,w,h)
{
	if(f_forcefocus)
	{
		var go = false;
		
		//Current Position
		var stx = 0, sty = 0;
		if(document.body.scrollLeft)
		    stx = document.body.scrollLeft;
		if(document.body.scrollTop)
		    sty = document.body.scrollTop;
		if(window.pageXOffset)
		    stx = window.pageXOffset;
		if(window.pageYOffset)
		    sty = window.pageYOffset;

        if(stx>0 || sty>0)
        {		
		    //Make sure the bottom/right point isn't out of the bottom/right
		    if(x+w>stx+q_GetBrowserWidth()) {go=true; stx = x+w-q_GetBrowserWidth();}
		    if(y+h>sty+q_GetBrowserHeight()) {go=true; sty = y+h-q_GetBrowserHeight();}

		    //Make sure the top/left point isn't out of the top/left (leave 8px gap)
		    if(x<stx) {go=true; stx=x-8; if(stx<0) stx=0}
		    if(y<sty) {go=true; sty=y-8; if(sty<0) sty=0;}
    		
		    //Scroll?
		    if(go) self.scrollTo(stx, sty);
	    }
	}
}

//=========================================================
//=================== FORM OBJECT =========================
//=========================================================


q_Init();


//---------------------------------------------------------
//------------------- Initializing Stuff ------------------
//---------------------------------------------------------


function q_Init()	//Must be called first, while page is loading
{
	var i,j,n;

	//---- Init Global Variables ---

	f_previous_onload = null; // Remember any other script's Onload event(s)
	f_absolute_pos = false;	// false = form is always at same coordinate (provided by User in windows.q_pos)
							// true = form is whereever the Loading pic is (moves on resize)
	f_form_x = 0;		//Current coordinates of form 
	f_form_y = 0;		//Current coordinates of form
	f_page_x = 0;		//Location of page (not skin)
	f_page_y = 0;		//Location of page (not skin)

	f_capturing_control = -1;		//Event handling
	f_flashing_steps = -1;			//Flashing Steps (Countdown)
	f_flashing_controls = null;		//Array of item indexs that are currently flashing
	f_disableskin = true;			//Is set to true once Send button is pressed
	f_confirmationmode = -1;		//Is set when only "Success" (1) or "Failure" (0) messages should be displayed (no form)
	f_current_control = -1;			//Control that has focus (used by scripting)
	f_scripts_disabled = false;		//Used during "Reset"
	f_preloading = false;			//Used during "Preloading Data", so that certain script functions are disabled
	f_multipageprinting = false;	//True while multipage printing is in progress
	f_additional_data = "";			//Additional string that is send with response data (usewd by WorkFlow)
	f_first_time_page = true;		//Used by GoToPage2 to know if it displaying a page for the 1st time
	f_currenteventsource = null;	//Used to avoid endless loops in event triggered scripting
	f_emailembedded = false;		//If true, form is embeded in email
	f_encrypted_preload = new Array();	//Preload data that has been encrypted
    f_debug_obj = null;             //Debug ActiveX object
    f_scripts_stack = new Array();  //Callstack for user scripting
	f_pagehistory = new Array();    //Stack for history of displayed pages

	f_current_page = -1;

	f_pressed_skinbutton = -1;
	f_pressed_skinbutton_x = -1;
	f_pressed_skinbutton_y = -1;
	
	f_msgbox_w = 200;									//Default width of Message box 
	if(f_msgbox_w>f_page_w-8) f_msgbox_w = f_page_w-8;	//Adapt width to small forms
	if(f_msgbox_w<100) f_msgbox_w=120;					//Minimum width
	f_msgbox_h = 150;	//Approx. height of Message box 


	//--- Calculate initial position of form ---
	
	//Did user provide absolute coordinates for the form?
	var p = window["q_pos"];
	if(p)
	{
		f_absolute_pos = true;
		f_form_x = p[0];
		f_form_y = p[1];
	}

	//Calculate page coordinates (not skin)
	f_page_x = f_form_x + f_skin_w;
	f_page_y = f_form_y + f_skin_h;


	//--- Decode Texts ---
	
	for(i=0; i<q_Texts.length; i++)
		q_Texts[i] = q_StupidDecode(q_Texts[i]);
		
	
	//--- Parse QueryString ---
	
	f_querystring = new Array();
	var qs = ""+location.search;
	if(qs.length>1)
	{
		qs = q_Unescape(qs.substring(qs.lastIndexOf("?")+1));
		var s = qs.split("&");
		for(i=0; i<s.length; i++)
		{
			var ss = s[i].split("=");
			if(ss.length>1)
				f_querystring[ss[0]] = ss[1];
		}
	}	


	//--- Parse Encoded QueryString ---
	
	if(f_querystring["qp"])
	{
		var s = q_QueryStringDecode(f_querystring["qp"], parseInt("0x"+f_guid.substring(0,2))&255).split("&");
		for(i=0; i<s.length; i++)
		{
			var ss = s[i].split("=");
			if(ss.length>1)
				f_querystring[ss[0]] = ss[1];
		}	
	}
			
			
	//--- Confirmation Mode (Data Success or Failure message only) ---
	
	var cf = f_querystring["fcSuccess"];
	if(cf=="0" || cf=="1") f_confirmationmode = parseInt(cf);
	
	//Special cases of AfterSend that affect Confirmation Mode
	switch(f_querystring["fcAfterSend"])
	{
		case "5":	//Re-start the form without confirmation

			if(f_confirmationmode==1)
			{			
				//Success: Restart form
				var l = "" + self.location;
				self.location = l.substring(0, l.lastIndexOf("?"));
			}	
			else
			{
				//Failure: Show failure confirmation with restart-link
				f_querystring["fcAfterSend"] = "1";
			}
			break;
			
		case "6":	//Close the browser window without confirmation

			if(f_confirmationmode==1)
			{			
				//Success: Close window
				self.close();
			}
			else
			{
				//Failure: Show failure confirmation with close-link
				f_querystring["fcAfterSend"] = "2";
			}
			break;
	}
		

	//--- Is there a RID ? ---
	
	f_rid = ""+f_querystring["fcRID"];
	if(f_rid.indexOf("undefined")>=0) f_rid="";


	//--- Preload Images ---

	f_loading = new Image();						//Loading image used in HTML
	f_loading.src = f_resources_path + "sl.gif";	//Must be first so it shows quickest
	f_resources_app = Array("gif", "jpg", "wav", "mid", "mp3");
	f_resources_n = f_resources_type.length; //Number of Resources

	//Control's Images Resources
	f_resources = new Array();						//0 must always be nope.gif; 1-5 must be Quask logo
	var m = (f_confirmationmode<0)?f_resources_n:6;	//Only do 1st 5, if in confirmation mode
	for(i=0; i<m; i++)
	{
		f_resources[i] = new Image();
		f_resources[i].src = f_resources_path + i + "."+f_resources_app[f_resources_type[i]];
	}

    if(f_skin)
    {
	    //Skin Buttons Images
	    f_skin_but_n = new Array();	//Normal State
	    f_skin_but_p = new Array(); //Pressed State
	    var si=0;
	    if(f_skin_btns==1) si=3;	//Preload Send/Reset/Print
	    if(f_skin_btns>1) si=5;		//Preload all buttons
	    for(i=0; i<si; i++)
	    {
		    f_skin_but_n[i] = new Image();
		    f_skin_but_n[i].src = f_resources_path + "s"+(5+i*2)+".gif";
		    f_skin_but_p[i] = new Image();
		    f_skin_but_p[i].src = f_resources_path + "s"+(6+i*2)+".gif";
	    }
    	
	    //Skin Quask Logo
	    f_skinlogo = f_resources_path+"s4.gif";
    }
    

    //--- Create Page and Control Objects ---
    
	//Don't do all the page and object creation, if in confirmation mode
	if(f_confirmationmode<0)
	{		
		
		//--- Create Pages Objects ---

		f_pages_n = f_page_def.length;	//Number Of pages in Form
		f_pages = new Array();
		for(i=0; i<f_pages_n; i++) f_pages[i] = new q_page(i, f_page_def[i]);

		//Page order
		f_page_order = new Array();
		for(i=0; i<f_pages_n; i++) f_page_order[i] = i;
		
		//Randomize Page Order					
		var random_found = -1;
		for(i=0; i<=f_pages_n; i++)
		{
			if(i!=f_pages_n && f_pages[i].randomize)
			{
				//New Randomize Sequence found
				if(random_found<0) random_found=i;
			}
			else 
			{
				if(random_found>=0)
				{
					//Existing Randomize Sequence has ended
					q_Randomize(f_page_order, random_found, i);
					random_found = -1;
				}
			}
		}
		
		//Page Order set from pre-load data?
		i = "qo_po";
		j = ",";
		n = null;
		if(f_encrypted_preload[i]) n = f_encrypted_preload[i].split(j);
		if(window[i]) n = window[i].split(j);
		if(f_querystring[i]) n = f_querystring[i].split(j);
		if(n!=null && n.length==f_page_order.length)	//Validate
			f_page_order = n;

		
		//--- Create Controls Objects ---

		f_controls_n = f_controls_def.length-1;	//Number of controls in form
		f_controls = new Array(f_controls_n);
		for(i=0; i<f_controls_n; i++)
		    f_controls[i] = new q_ctrl(i, f_controls_def[i]);
		
	
		//--- Is it Single Response and already answered? ---
		
		if(f_singleresponse && q_CheckSingleResponse(f_rid + f_guid))
			f_confirmationmode = 2;


		//-- Handle Email Embed stuff ---
		
		if(window.qs_emailembedded)
		{
			f_emailembedded = true;
			
			//Follow up URLs (cannot come back to myself)
			if(f_success_url=="") f_success_url = f_self_url; 
			if(f_failure_url=="") f_failure_url = f_self_url; 
		}
	}


	//--- System Variables (they are sent to the Data-handling script) ---
	
	f_system = new Array();
	
	//Default Send/Failure URLs
	if(f_success_url=="") f_success_url = self.location;
	if(f_failure_url=="") f_failure_url = self.location;

	//Source location (is it only relative or full?)
	if(f_src_url.indexOf("//")<0)
	{
		//Construct full path
		var l = self.location,
			pn = l.pathname,
			pns = pn.lastIndexOf("/");
		if(pns>0) pn = pn.substring(0, pns);
		else pn = "";
		f_src_url = "http://" + l.host + pn + "/" + f_src_url;
	}
		
	//Set required values. More can be added by scripting
	f_system["appName"] = "HTML Form";
	f_system["appVersion"] = f_appversion;
	f_system["guid"] = f_guid;
	f_system["version"] = f_version;
	f_system["tag"] = f_tag;
	f_system["title"] = f_title;
	f_system["successURL"] = f_success_url;
	f_system["failureURL"] = f_failure_url;
	f_system["singleResponse"] = f_singleresponse?"true":"false";
	f_system["rid"] = f_rid;
	f_system["source"] = f_src_url;
	f_system["afterSend"] = f_aftersend;
	f_system["ipAddress"] = ""; //To be filled in by ASP/PHP script
	f_system["workflowstage"] = f_initial_workflowstage;	//Default
	f_system["workflowlevel"] = f_intitial_workflowlevel;	//Default
	f_system["WFSCtr"] = 0;     //WorkFlow Counter
    f_system["WFFCtr"] = 0;     //WorkFlow Counter
	//f_system["started"] = 0;	//Used by split-page, if 1 then this is not the 1st time we are starting..


	//---- Decrypt Encrypted Preload Data ---
	
	if(f_encryption && window["q_epl"])
	{
		//Get it and split it by line ("\n")
		var arr = (q_DecryptPreloadData(window["q_epl"])).split("\n");
		n=0;
		for(i=0; i<arr.length; i++)
		{
			//Find first "="
			var g=arr[i].indexOf("=");
			if(g>0) f_encrypted_preload[n++] = Array(arr[i].substring(0,g), arr[i].substring(g+1));
			//alert(arr[i]);
		}
	}

	//--- Preload any System Variables / Form Properties ---

	//Overrides from Encrytped Preload Data
	for(n in f_encrypted_preload) q_HandlePreloadPoperties(f_encrypted_preload[n][0], f_encrypted_preload[n][1]);

	//Overrides from JavaScript
	for(n in window) q_HandlePreloadPoperties(n, window[n]);

	//Overrides data from QueryString
	for(n in f_querystring) q_HandlePreloadPoperties(n, f_querystring[n]);
}


//--- Write all HTML for Form ---

function q_WriteHTML() //Must be called after q_Init() !!!
{
	var h = "";


    //--- Write some generic styles ---
    
   	var h = '<style type="text/css">';
	
	h +='.st_d {position: absolute; visibility: hidden; top: 0; left: '+((q_bMoz15)?'-1000':'0')+'}\n'
	 +  '#p_d {left: ' + f_page_x + 'px; top: ' + f_page_y + 'px}\n'
	 +	'.st_nb {background-image: none}\n'
	 +	'.st_p {cursor: hand; cursor: pointer}\n'
	 +	'.st_op {filter:alpha(opacity=100)}\n'
	 +	'.st_ql {font-size: ' + ((f_page_w>200)?9:8) + 'pt; font-family: Sans-Serif; color: #637628}\n'
	 +	'.st_ql2 {font-size: ' + ((f_page_w>200)?8:7) + 'pt; font-family: Sans-Serif; color: #939393}\n';

	//Skin Styles
	if(f_skin)
	    h += "#s_d {left: " + f_form_x + "px; top: " + f_form_y + "px}\n"
		 + '.st_bs {background-image: url("'+f_resources_path+'s3.gif")}\n'
		 + '.st_pc {font-size: 9; width: '+(5*f_skin_w)+'}\n';

    h += '</style>\n';


	//Write Sound-Resources <embeds>
	soundfound=false;
	for(var i=0; i<f_resources_n; i++)
	{
		t=f_resources_type[i];
		if(t==2||t==3||t==4)
		{
			//Pre-loads
			//q_PreLoadSound(i);
			soundfound=true;
		}		
	}
	//Object for playing Sound in IE
	if(soundfound) h += '<bgsound id=q_snd_noloop loop=1><bgsound id=q_snd_loop loop=infinite>\n';

	//Write Form for sending data back
	h += '<form name="q_data" method="post"><input type="hidden" name="data" value=0><input type="hidden" name="id" value=0><input type="hidden" name="lookup" value=0><input type="hidden" name="session" value=""></form>\n';
	
	
	//Write Skin layer
	if(f_skin)
	{
		//Skin
		h+= '<div id=s_d class=st_d>'
		+	'<table cellspacing=0 cellpadding=0 border=0 width='+(f_page_w+2*f_skin_w)+'>'
		+		'<tr><td colspan=3 width='+(f_page_w+2*f_skin_w)+' height='+f_skin_h+'><img src="'+f_resources_path+'s0.gif" width='+(f_page_w+2*f_skin_w)+' height='+f_skin_h+'></td></tr>'
		+	'<tr><td width='+f_skin_w+' height='+f_page_h+'><img src="'+f_resources_path+'s1.gif" width='+f_skin_w+' height='+f_page_h+'></td>'
		+			'<td width='+f_page_w+' height='+f_page_h+'><img src="'+f_resources_path+'0.gif" width='+f_page_w+' height='+f_page_h+' galleryimg=no></td>'
		+			'<td width='+f_skin_w+' height='+f_page_h+'><img src="'+f_resources_path+'s2.gif" width='+f_skin_w+' height='+f_page_h+'></td>'
		+	'</tr>'
		+	'<tr><td colspan=3 width='+(f_page_w+2*f_skin_w)+' height='+(f_skin_btns!=4?3:5)*f_skin_h+' valign=center class=st_bs>\n'
		
		+		'<table cellspacing=0 cellpadding=0 border=0 width='+(f_page_w+2*f_skin_w)+'>'
		+			'<form name="f_s_d" method="post">'
		+			'<tr width='+(f_page_w+2*f_skin_w)+'>'
		+				'<td class=st_nb width='+f_skin_w+'><img src="'+f_resources[0].src+'" width='+f_skin_w+' height='+f_skin_h+'></td>';
		
		if(f_unbranded) h += '<td class=st_nb width='+f_skin_w+' valign=top><img src="'+f_resources[0].src+'" width='+f_skin_w+' height='+f_skin_h+'></td>';
		else h += '<td class=st_nb width='+f_skin_w+' valign=top><img src="'+f_skinlogo+'" name=sb_9 width='+f_skin_w+' height='+f_skin_h+' class=st_p></td>';

		h += '<td class=st_nb width='+(f_page_w-f_skin_w)+' align=right>\n';

			
		if(f_skin_btns==0)
		{
			h += "&nbsp;";
		}
		else
		{
			//Write Skin Buttons
			h +=	'<table cellspacing=0 cellpadding=0 border=0>'
				+	'<tr><td align=right class=st_nb>';
			
			//Send & Reset Buttons
			if(f_skin_btns==1||f_skin_btns>=3)
			{
				h +='<table cellspacing=0 cellpadding=0 border=0><tr>'
				 +	'<td><img src="'+f_resources_path+'s5.gif" name=sb_0 width='+3*f_skin_w+' height='+f_skin_h+' class=st_p></td>'
				 +	'<td><img src="'+f_resources_path+'s7.gif" name=sb_1 width='+3*f_skin_w+' height='+f_skin_h+' class=st_p></td>'
				 +	'<td><img src="'+f_resources_path+'s9.gif" name=sb_2 width='+3*f_skin_w+' height='+f_skin_h+' class=st_p></td>'
				 +	'</tr></table>\n';
			}
			
			if(f_skin_btns!=4)
				//On 1 line
				h += '</td><td class=st_nb>';
			else	
				//On 2 lines
				h += '</td></tr><tr><td class=st_nb><img src="'+f_resources[0].src+'" width='+f_skin_w+' height='+f_skin_h+'></td></tr><tr><td class=st_nb align=right>';
			
			//Page Navi Buttons
			if(f_skin_btns>=2)
			{
				h +='<table cellspacing=0 cellpadding=0 border=0><tr>'
				 +		'<td><img src="'+f_resources_path+'s11.gif" name=sb_3 width='+2*f_skin_w+' height='+f_skin_h+' class=st_p></td>'
				 +		'<td><select name="p_cb" onchange="q_SkinPageComboChanged();" class=st_pc>';

				if(f_confirmationmode<0)
				{
					for(var i=0; i<f_pages_n; i++) h += "<option value="+f_page_order[i]+">" + f_pages[f_page_order[i]].name;
				}

				h +=	'</select><br></td>'
				 +		'<td><img src="'+f_resources_path+'s13.gif" name=sb_4 width='+2*f_skin_w+' height='+f_skin_h+' class=st_p></td>'
				 +	'</tr></table>';
			}
			
			//End of buttons
			h += '</tr></table>\n';
		}
		
		//End of Skin
		h += 	'</td>'
		 +	'<td class=st_nb width='+f_skin_w+'><img src="'+f_resources[0].src+'" width='+f_skin_w+' height='+f_skin_h+'></td>'
		 +	'</tr></form></table>'
		 + '</td></tr></table></div>\n';
	}

	//Write page background
	h+=	'<div id="p_d" class="st_d">'
	 +	'<table cellspacing=0 cellpadding=0 border=0 width='+f_page_w+'>'
	 +	'<tr><td width='+f_page_w+' height='+f_page_h+'><img src="'+f_resources[0].src+'" width='+f_page_w+' height='+f_page_h+' galleryimg=no></td></tr>'
	 +	'</table></div>\n';
		    
	//Write it all out
	document.write(h);


	if(f_confirmationmode<0) 	//Don't write these if confirmation screen only
	{
		//Write Trial Version layer
		if(f_trialversion)
			document.write('<div id=p_qtv class=st_d>'+q_GetMsgBoxHTML(q_Texts[5]+'<br><br><a href="#" onmousedown="q_Start2();" class=st_ql>'+q_Texts[14]+'</a>') + '</div>');

		//Write Hour Glass layer
		if(f_hourglass>=0)
			document.write('<div id=p_hrg class=st_d><img src="' + f_resources[f_hourglass].src + '" width=31 height=31></div>');
	}
			

	//Write "Powered by Quask" Logo layer, either
	//-Preview Mode
	//-Sending Data....
	//-Data Successfully Sent
	//-Already filled in
	
	var msg = q_Texts[0];						//"Sending..."
	if(f_emailembedded) msg=q_Texts[16];		//"Sending... Confirmation will be displayed in new window."
	if(f_preview) msg=q_Texts[1];				//"Preview Mode"
	if(f_confirmationmode==0) msg=q_Texts[2] //"Sending failed."
		+ '<br><br><a href="javascript:q_ShowError();" class=st_ql><font size=1>'+q_Texts[15]+'</font></a>'; //"Details..."
	if(f_confirmationmode==1) msg=q_Texts[3];	//"Data Successfully Sent"
	if(f_confirmationmode==2) msg=q_Texts[4];	//"This form can only be filled in once."
	

	//After send behaviour
	if(f_confirmationmode==0 ||f_confirmationmode==1)
	{
		if(f_querystring["fcAfterSend"]=="1")
		{
			var l = "" + self.location;
			l = l.substring(0, l.lastIndexOf("?"));
			msg += '<br><br><a href="'+l+'" class=st_ql>'+q_Texts[13]+'</a>';
		}
		if(f_querystring["fcAfterSend"]=="2")
			msg += '<br><br><a href="javascript:window.close();" class=st_ql>'+q_Texts[12]+'</a>';
	}
	
	document.write('<div id=p_ql class=st_d>'+q_GetMsgBoxHTML(msg)+'</div>');
	
	
	//--- Trap OnLoad and OnUnload events ---

	//Add "OnLoad" event. 
	if(!(q_bMac && navigator.appVersion.indexOf("MSIE 4.")!=-1) && window.onload)	
		f_previous_onload = window.onload;	//Remember if there is already one
	window.onload = q_Start;				//Replace it with ours

	//Add "OnUnLoad" event. 
	window.onunload = q_Unload;				//Replace it with ours

}


//--- Start Form (After page has loaded) ---

function q_Start() 	//Must be called after q_WriteHTML() !!!
{
	//Is there another Event to run OnLoad, if yes execute it?
	if(f_previous_onload!=null) f_previous_onload();
		
	//If not absolut position, move it to right place
	if(!f_absolute_pos) q_RePositionForm();

	//Does form need to be reposition when the browser window changes?
	if(!f_absolute_pos) window.onresize = q_OnResize;

	//Show skin and page background
	if(f_skin) q_SetVisible("s_d", true);
	q_SetVisible("p_d", true);
	
	
	//Preload and ReadOnly (but not if in confirmation mode)
	if(f_confirmationmode<0)
	{
		//Preload
		if(f_allowpreload)
		{
			//Set status flag, to disable certain scripting functions
			f_preloading = true;
	
			//Pre-load from Encrypted Preload String
			for(var n in f_encrypted_preload) q_HandlePreloadData(f_encrypted_preload[n][0], f_encrypted_preload[n][1]);
	
			//Pre-load (and pre-populuate) data from JavaScript
			for(var n in window) q_HandlePreloadData(n, window[n]);
			
			//Pre-load data from QueryString
			for(var n in f_querystring) q_HandlePreloadData(n, f_querystring[n]);
						
			//Clear status flag
			f_preloading = false;
		}
		
		//Global ReadOnly?
		if(f_readonly)
			for(var i=0; i<f_controls_n; i++)
				f_controls[i].SetReadOnly(true);
	}
	
	//Remove Loading Pic
	if(document.images[f_loading_image_id])
		document.images[f_loading_image_id].src = f_resources[0].src;
	
	//Show Confirmation Only?
	if(f_confirmationmode>=0)
	{
		//Set Default-Background Color
		q_SetBackCol("p_d", f_skin_defaultcolor);

		//Show confirmation screen
		q_ShowMsgBox("p_ql");
		
		//That's it
		return;
	}
				
	//Start with Page 1 or show Trial Version screen
	if(f_trialversion)
	{
		//Show trial Screen
		
		//Set Default-Background Color
		q_SetBackCol("p_d", f_skin_defaultcolor);
		
		//Show Box
		q_ShowMsgBox("p_qtv");
		
		//Tiner just in case
		setTimeout("q_Start2();", 5000);
	}
	else q_Start2();
}

function q_Start2()
{
	//Avoid double start (from Tiral Version timer)
	if(f_current_page>=0) return;
		
	//Hide Trial Message
	if(f_trialversion) q_SetVisible("p_qtv", false);
	
	//Initialize browser event capturing
	q_InitEvents();

	//Trigger Scripts/control events
	//if(f_system["started"]==0)
	f_OnFormStart();
			
	//Show 1st page
	//if(f_splitpage && f_system["started"]!=0)
	//	f_GoToPage(f_page_start);
	//else
	if(f_current_page<0) //Only if a particular page is already being shown by OnFormStart event (GoToPage command)
	    f_GoToPage(f_page_order[f_page_start]);
	
	//Enable Skin Buttons
	f_disableskin = false;
			
	//Do Pop-Up Test (display message if pop-up blocker found)
	if(f_requirespopup && !f_preview && !f_readonly)    //f_system["started"]==0 && 
		setTimeout("q_PopUpTest();", 100);

    //Start Keep-Alive Timer
    if(f_keepalive_url!="") q_KeepAlive(false);
        		
	//Split-Page: Remember that this isn't the first time
	//f_system["started"] = 1;
}

//Helper (also called OnResize if form is right/center x-aligned)
function q_RePositionForm()
{
	
	// If relative positionning, update position of form
	if(!f_absolute_pos)
	{
		// Get position of Loading Image is
		var p = q_GetImagePagePos(f_loading_image_id);
		f_form_x = p[0];
		f_form_y = p[1];
	}

	//Re-position skin
	if(f_skin)
	{
		q_SetLeft("s_d", f_form_x);
		q_SetTop("s_d", f_form_y);
	}

	//Calculate page coordinates (not skin)
	f_page_x = f_form_x + f_skin_w;
	f_page_y = f_form_y + f_skin_h;

	//Re-position page background
	q_SetLeft("p_d", f_page_x);
	q_SetTop("p_d", f_page_y);
}

//Enterprise Only: Trigger URL when browser is closed
function q_Unload()
{
    //Notify Debug component
	if(f_debug_obj!=null)
         f_debug_obj.Quit();
    
	//Notify of window close (but only if data wasn't sent yet)
	if(f_unload_url!="" && !f_disableskin && f_confirmationmode<0)
	{
		//Try to create Ajax object
		var req = q_GetHTTPRequestObject();
		if(req) 
		{
			//Yes, do Ajax: Make the synchronous call!
			req.open("GET", f_unload_url, false);
    		req.send(null);
	    	var a = req.responseText; //Wait for, but ignore response
		}
		else
		    //Do pop-up
    		q_OpenWindow(f_unload_url, 200, 100);
	}
}

function q_PopUpTest()
{
	var w = q_OpenWindow(f_data_url, 100, 100);
	if(w==null) alert(q_Texts[20]);
	else w.close();
}



//---------------------------------------------------------
//--------------- Page Navigation Methods -----------------
//---------------------------------------------------------


function f_GoToPage(i, r)  //r=true if Reset button is pressed, this forces OnPageLoad trigger even if already on page 1 
{
	if(i>=0 && i<f_pages_n && (f_current_page!=i || r==true) && !f_preloading)
	{
		//Event Trigger: On Page Unload
		if(f_current_page>=0 && !(r==true) && !f_multipageprinting)
		    f_OnPageBlur(f_current_page); 

		//Add new page to history stack, but not same page twice in arow
		if(!f_multipageprinting && f_pagehistory[f_pagehistory.length-1]!=i)
		    f_pagehistory.push(i);
			
		f_current_page = i;

		//Show hour glass layer?
		//if(f_hourglass>=0 && q_RepositionCtrlsInBackground() && f_controls_repositioned<f_controls_n && !f_multipageprinting)
		//{
		//	//Yes
		//	q_ShowHourGlassLayer();
		//	setTimeout("q_GoToPage2();", 1);
		//}
		//else
		//{
		//	//No
			q_GoToPage2();
		//}
	}
}

function q_GoToPage2()
{	
	//Change cursor
	q_SetHourglass(true);
		
	//Hide Controls from previous page
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].showing && f_controls[i].page!=f_current_page)
			f_controls[i].Show(false);
	
	//Set Background Color
	q_SetBackCol("p_d", f_pages[f_current_page].color);
	
	//Show Controls from current page
	for(var i=0; i<f_controls_n; i++)
	{
		if(f_controls[i].page==f_current_page && !f_controls[i].showing)
			f_controls[i].Show(true);
	}
			
	//Make sure it's in view (but not the 1st time)
	if(f_first_time_page)
		f_first_time_page = false;
	else
		q_ScrollIn(f_page_x, f_page_y, f_page_w, f_page_h);
	
	//Set the right combox-item in skin's page selection
	if(f_skin_btns>=2) q_SetSelectedValue("s_d", "p_cb", q_GetIndex(f_page_order, f_current_page));

	//Change cursor
	q_SetHourglass(false);

	//Hide hour glass layer
	//if(f_hourglass>=0 && q_RepositionCtrlsInBackground())
	//		q_SetVisible("p_hrg", false);

	//Event Trigger
	if(!f_multipageprinting) f_OnPageFocus(f_current_page);
}

//Split-Pages: Show page a new URL
function q_GoToPageURL2(i)
{
	return q_PostToURL(f_self_url, false, escape(q_GetDataXML()), i);
}

function q_PrevPage()
{
	//Get order position of current page
	var o = q_GetIndex(f_page_order, f_current_page);
	
	if(o>0) f_GoToPage(f_page_order[o-1]);
}

function q_NextPage()
{
	//Get order position of current page
	var o = q_GetIndex(f_page_order, f_current_page);

	if(o<f_pages_n-1) f_GoToPage(f_page_order[o+1]);
}

function q_BackHistoryPage() //Goes to previously displayed page (like in Browser)
{
   	//Get from history stack and show it
    if(f_pagehistory.length>1)
    {
        //Remove current page
        f_pagehistory.pop();
        
        //Get previous page, but leave it on stack
	    f_GoToPage(f_pagehistory[f_pagehistory.length-1]);
	}
}

function q_GoToPageName(name)
{
	for(var i=0; i<f_pages_n; i++)
	{
		if(f_pages[i].name==name)
		{
			f_GoToPage(i);
			return;			
		}
	}
}

function q_GoToPageID(id) //Used by scripting
{
	for(var i=0; i<f_pages_n; i++)
	{
		if(f_pages[i].id==id)
		{
			f_GoToPage(i);
			return;			
		}
	}
}

function f_HidePage()	//Important: No OnPageFocus/Blur events are trigged here
{
	//Hide Controls
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].showing)
			f_controls[i].Show(false);
			
	//Set Default-Background Color
	q_SetBackCol("p_d", f_skin_defaultcolor);
}

function q_GoToControl(id, h) //h = highlight true/false
{
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].id==id)
		{
			var c = f_controls[i];
			
			//Move to page where this control is located
			f_GoToPage(c.page);
			
			//Make sure control is visible
			if(!c.GetVisible()) c.SetVisible(true);
				
			//Make sure it is in view
			q_ScrollIn(f_page_x + c.x, f_page_y + c.y, c.width, c.height);
			
			//Start highlighting "Flashing"
			if(h) c.StartFlashing(6);
			
			return;
		}
}

function q_ShowHourGlassLayer()
{
	var id="p_hrg";
	q_SetLeft(id, f_page_x+(f_page_w-31)/2);
	q_SetTop(id, f_page_y+(f_page_h-31)/2);
	q_SetZOrder(id, "99999");
	q_SetVisible(id, true);
}

function q_GetSelectedValue(id, eid)
{
	var i=document.forms["f_"+id].elements[eid].options.selectedIndex;
	if(i<0)return null;
	else return document.forms["f_"+id].elements[eid].options[i].value;
}
function q_SetSelectedValue(id, eid, i)	{document.forms["f_"+id].elements[eid].options[i].selected=true;}



//---------------------------------------------------------
//--------------- Data Send/Reset Methods -----------------
//---------------------------------------------------------


function q_SendData(p)
{
	//Don't send if ReadOnly
	if(f_readonly) return;

	//Change AfterSend mode?
	if(p*1==p) f_system["afterSend"] = ""+p;
	
	//Check Obligatory Stuff
	var ok = true;
	for(var i=0; i<f_controls_n; i++)
	{
		var c = f_controls[i];
		 
		if(c.CheckValid()!=null)
		{
			//Invalid field found!
			alert(c.CheckValid());
			ok = false;
		}

		if(!c.CheckObligatory())
		{
			//Unanswered obligatory field found!
			alert(q_Texts[6]);
			ok = false;
		}
		
		if(!ok)
		{	
			//Move to page where this control is located
			f_GoToPage(c.page);
			
			//Start "Flashing"
			c.StartFlashing(6);
						
			//Don't continue sending
			return;
		}	
	}
		
	//Event Trigger (Form OnSend) (if return value is true, abandon sending)
	if(f_events!=0 && q_RunScript(f_events[1])) return;

	//Is it demo mode?
	if(f_aftersend=="9")
	{
		window.close();
		return;
	}

	//Obligatory test passed: Get XML data, and send it
	
	//Show "Sending..." msg
	f_HidePage();	
	f_disableskin = true;		//Disable buttons from now on
	q_ShowMsgBox("p_ql");
	
	//Submit form to data url
	if(!f_preview)
	{
		var f = document.forms["q_data"];
		f.action= f_data_url;
		f.target = (f_emailembedded)?"_blank":"_self";

		//Get Data
		var d = q_GetDataXML();		
		if(f_encryption && q_Encrypt_Key) d = "#QFS#" + q_EncryptResponseData(d);	//Encryption
		else d = escape(d);															//No encryption
		f.elements["data"].value = d; 
		f.elements["session"].value = window["q_se"];


		if(f_sendformmanager)
		{
			//Send the FormManager way
			window.status = "_fm_";
		}
		else
		{	
			//Send by POST			
			
			//If Branded and custom follow-up URLs, delay so the Quask message shows
			if(f_unbranded || (f_system["successURL"]==self.location && f_system["failureURL"]==self.location))
				f.submit();
			else
				setTimeout("document.forms['q_data'].submit();", 2800);
		}
	}
}


function q_GetDataXML()
{
	var xml, na;
		
	//Compile <fields> tag with all field=data inside
	xml = '<fields';

	for(na in f_system) xml += ' ' + na + '="' + q_XMLEncode(f_system[na]) + '"';

	//Store Time Stamp
	var dt = new Date();
	xml += ' time="' + q_ForceDigits(dt.getUTCFullYear(), 4) + q_ForceDigits(dt.getUTCMonth()+1, 2)
			+ q_ForceDigits(dt.getUTCDate(), 2) + " " + q_ForceDigits(dt.getUTCHours(), 2) + ":"
			+ q_ForceDigits(dt.getUTCMinutes(), 2) + ":" + q_ForceDigits(dt.getUTCSeconds(), 2) + '">';
	
	//Add each control's data
	for(var i=0; i<f_controls_n; i++)
	{
		//Get Data
		var c = f_controls[i];
		var d = c.GetData();
		
		//Get <field> tags
		if(d!=null)
			for(var j=0; j<d.length; j++)
				xml += q_GetFieldXMLTag(d[j], c);
	}
		
	//Pass "fc"-variables from QueryString
	var fn;
	for(fn in f_querystring)
		if((fn+"xx").substring(0,2)=="fc")
				xml += '<field id="'+(fn+"").substring(2)+'">'+f_querystring[fn]+'</field>';
	
	//Add form state info
	if(1)
	{	
		//Form State
		xml += "<state><page>"+f_current_page+"</page><pagehistory>"+f_pagehistory+"</pagehistory><pageorder>"+f_page_order+"</pageorder>";
		var s="";
				
		//Controls State
		for(var i=0; i<f_controls_n; i++)
		{
			var c = f_controls[i];
			
			if(c.changed>0)
			{
				//Also send changed properties info
				s += '<object id="'+c.id+'"';					
				
				if(c.changed&1) s += ' x="' + c.x + '"';
				if(c.changed&2) s += ' y="' + c.y + '"';
				if(c.changed&4) s += ' zorder="' + c.zorder + '"';
				if(c.changed&8) s += ' backcol="' + c.backcol + '"';
				if(c.changed&16) s += ' enabled="' + (c.enabled?1:0) + '"';
				if(c.changed&32) s += ' readonly="' + (c.readonly?1:0) + '"';
				if(c.changed&64) s += ' shaded="' + (c.shaded?1:0) + '"';
				if(c.changed&128) s += ' visible="' + (c.visible?1:0) + '"';
				if(c.changed&256) s += ' tag="' + q_XMLEncode(c.tag) + '"';
				if(c.changed&512) s += ' transparency="' + c.transparency + '"';
				if(c.changed&2048) s += ' source="' + q_XMLEncode(c.source) + '"';
				if(c.changed&4096) s += ' caption="' + q_XMLEncode(c.caption) + '"';
				if(c.changed&8192) s += ' touched="' + (c.untouched?0:1) + '"';
				if(c.changed&16384) s += ' lastselected="' + c.lastselected + '"';
				if(c.changed&32768) s += ' flashing="' + c.flashing + '"';
				if(c.changed&1024)
				{
				    //Answers can be array, or string
				    if(q_IsArray(c.changedanswers))
	   			        for(var j in c.changedanswers)
	    			        s += ' answers_' + j + '="' + q_XMLEncode(c.changedanswers[j]) + '"'; 
				    else
				        s += ' answers="' + q_XMLEncode(c.changedanswers) + '"'; 
				}

				s += '/>';					
			}
		}
		
		xml += s+"</state>";
	}
		
	//Additional data and closing field tag
	xml += f_additional_data + '</fields>';
	
	//Add parent tags
	return q_GetParentXMLTag(xml);
}

//Data XML Helper: Put parent tags around <fields> tag
function q_GetParentXMLTag(f) //f=<fields> tag string
{
	// '<?xml version="1.0" encoding="ISO-8859-1" ?>'

	return 	'<quaskformdata xmlns="http://www.quask.com/quaskformserver/quaskformdata">'
		+	'<forms><form guid="'+f_guid+'"><data>'
		+	f
		+	'</data></form></forms></quaskformdata>';
}

//Data XML Helper: Return <field> tag
function q_GetFieldXMLTag(d, c) //d=data string, c=control
{
	//Default
	var xml = "";
	
	//Split from first |
	var s = d.indexOf("|"); 
	if(s>0)
	{
		xml += '<field id="'+d.substring(0, s)+'"';
		if(c!=null && ((""+c.tag).length>0 || (c.changed&256)>0)) xml += ' tag="' + q_XMLEncode(c.tag) + '"';
		xml += '>'+q_XMLEncode(d.substring(s+1))+'</field>';
	}
	
	return xml;
}

//Customization for Customer
function q_GetDataXMLAlt()
{
	//Default
	var xml = "";
	
	//Add each control's data
	for(var i=0; i<f_controls_n; i++)
	{
		//Get Data
		var c = f_controls[i];
		var d = c.GetData();
		
		//Get fields
		if(d!=null)
			for(var j=0; j<d.length; j++)
			{
	            //Split from first |
	            var s = d[j].indexOf("|"); 
	            if(s>0)
	            {
	                //Tag name
	                var n = "field_"+d[j].substring(0, s);
	                
	                //Add tag
		            xml += '<' + n;
		            if((""+c.tag).length>0 || (c.changed&256)>0) xml += ' tag="' + q_XMLEncode(c.tag) + '"';
		            xml += '>'+q_XMLEncode(d[j].substring(s+1))+'</'  + n + '>';
	            }
			}
	}
	
	//Add parent tags
	return q_GetParentXMLTag(xml);
}

function q_ResetData()
{
	//Don't send if ReadOnly
	if(f_readonly) return;

	//Ask first
	if(confirm(q_Texts[7])) //"Are you sure you want to reset each field in this form?"
	{
		//Event Trigger (Form OnReset)
    	if(f_events!=0)
	    	q_RunScript(f_events[2]);
		
		//Reset each control
		for(var i=0; i<f_controls_n; i++) f_controls[i].ResetData();
		
		//Go to first page
		f_GoToPage(0, true); //true = special event trigger mode
	}
}

//Flashing controls timer
function q_Flashing()
{
	if(f_flashing_controls!=null)
	{
		//Handle multiple items
		for(var j=0; j<f_flashing_controls.length; j++)
		{
			var c = f_flashing_controls[j];
			c.flashing = f_flashing_steps;	//Update state info
			c.Show(f_flashing_steps&1 && c.page==f_current_page);
		}
	
		//Count down	
		f_flashing_steps--;
		
		if(f_flashing_steps>0)
		{	
			//Keep flashing
			setTimeout("q_Flashing();", 300);
		}	
		else
		{
			//Stop flashing
			for(var j=0; j<f_flashing_controls.length; j++)
			{
				var c = f_flashing_controls[j];
				c.flashing = 0;				//Clear state info
				c.changed &= (-32769);		//Clear state info (hex FFF7FFF)
				c.Show(c.visible && c.page==f_current_page);
			}
			
			//Clear Array
			f_flashing_controls = null;
		}
	}
}



//---------------------------------------------------------
//-------------------- Preload Helpers ---------------------
//---------------------------------------------------------


//--- Preloading (form) properties (before form objects are created, q_Init) ---

function q_HandlePreloadPoperties(name, value)
{
	//Unload function?
	if(name=="q_ul") f_unload_url = value;

	//2nd part of name
	var e = name.substring(3);				

	switch(name.substring(0,3))
	{ 
	case "qs_":
		f_system[e] = value;
		return;

	case "qf_":
		 return q_SetFormProperty(e, value);
	}
}


//--- Preloading (object) data (after objects have been created, in q_Start) ---

function q_HandlePreloadData(name, value)
{
	//Object ID
	var e = name.substring(3);				
	
	switch(name.substring(0,3))
	{ 
	case "qa_":
		return q_SetAnswers(e, value);

	case "qd_":
		return q_SetData(e, value);
		
	case "qt_":
		return q_SetDataByTag(e, value);
		
	case "qo_":
		return q_SetStateProperties(e, value);
	}
}

function q_SetData(fieldname, value)
{
	//Check all controls if they "own" this fieldname
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].SetData(fieldname, value)) return true;
		
	//No control replied
	return false;
}


function q_SetDataByTag(tagname, value)
{
	//Check all controls if they "own" this tag name
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].tag.toLowerCase()==tagname.toLowerCase())
			return f_controls[i].SetValue(value);
		
	//No control found
	return false;
}


function q_SetStateProperties(id, p)
{
	//Form State
	switch(id)
	{
		case "pn":	//Current Page Number (Start page)
			f_page_start = parseInt(p);
			return;

		case "ph":	//Page History
			f_pagehistory = p.split(",");
			return;
	}
	
	//Object State
	var c = q_GetControlByID(id);
	if(c!=null)
	{
		var pr = p.split(";");
		for(var i=0; i<pr.length; i++)
		{
			var po = pr[i].split("=");
			if(po.length>1)
			{
				var a = po[1];
				switch(po[0])
				{
				case "x":
					c.SetX(parseInt(a));
					break;
					
				case "y":
					c.SetY(parseInt(a));
					break;

				case "zorder":
					c.SetZOrder(parseInt(a));
					break;

				case "backcol":
					c.SetBackCol(a);
					break;

				case "enabled":
					c.SetEnabled(a>0);
					break;

				case "readonly":
					c.SetReadOnly(a>0);
					break;

				case "shaded":
					c.SetShaded(a>0);
					break;

				case "visible":
					c.SetVisible(a>0);
					break;

				case "tag":
					c.SetTag(a);
					break;
					
				case "transparency":
					c.SetTransparency(parseInt(a));
					break;

				case "answers":
					c.SetAnswers(a);
					break;
					
				case "source":
					c.SetSource(a);
					break;
					
				case "caption":
					c.SetCaption(a);
					break;
					
				case "touched":
					c.SetUntouched(a==0);
					break;
					
				case "lastselected":
					c.lastselected = parseInt(a);
					break;
					
				case "flashing":
					c.StartFlashing(parseInt(a));
					break;

				case "downloadurl":
					c.SetDownloadURL(a);
					break;
					
				default:
					//Special case: Table object can have array of answers (e.g."answers_3")
					if(po[0].indexOf("answers_")==0)
						c.SetAnswers(a, parseInt(po[0].substring(8)));
				}
			}
		}
	}
}


function q_SetAnswers(ctrlid, answers)
{
	var c = q_GetControlByID(ctrlid);
	if(c!=null) c.SetAnswers(answers);
}



//---------------------------------------------------------
//-------------------- Misc Methods -----------------------
//---------------------------------------------------------


function q_Print()
{
	if(f_pages_n==1 || f_splitpage)
	{
		//Only one page to print
		window.print();
	}
	else
	{
		//More than one page to print
		if(q_SupportsMultipagePrinting())
		{
			if(confirm(q_Texts[9]))
						// "You will be presented with a Print dialog for each page in this form.\n\r\n\r"
						// "Press 'Print' on each dialog to print the complete form.\n\r\n\r"
						// "Alternatively, you can print single pages using your Browser's print function."
			{
				//Remember current page
				var p = f_current_page;
				
				//Print each page
				f_multipageprinting = true;		//Make sure hourglass is not shown etc...
				for(var i=0; i<f_pages_n; i++)
				{
					f_GoToPage(i);
					window.print();
				}
				
				//Go back to current page
				f_GoToPage(p);
				f_multipageprinting = false;	//Default
			}
		}
		else
		{
			if(confirm(q_Texts[10]))
					// "Your browser only supports printing one page at the time.\n\r\n\r"
					// "Only the current page will be printed.\n\r\n\r"
					// "Navigate to the other pages and press Print again after this page has finished printing."
			{
				//Print current page
				window.print();
			}
		
		}
	}
}

function q_ShowURL(u, b, x, y)	//u=URL, b=Minimal Style?, x,y = Size
{
	if(b)q_OpenWindow(u, x, y);
	else window.open(u);
}

function q_PostToURL(u, b, da, id, x, y)	//u = URL, b = open new Window?, da = Data-Param, id = ID-Param, x,y = Size of new window
{
    //Get form
    var f = document.forms["q_data"];

    //Open New Window ?
    if(b)
    {
        //New window
        var n = "wnd"+Math.floor(Math.random()*100000);
	    window.open("", n, "location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes"
	             + ((x>0)?(",width="+x):"")
	             + ((y>0)?(",height="+y):""));
        f.target = n;
    }
    else
    {
        //Same window as form
        f.target = "_self";
    }    

    f.action = u;
    f.elements["data"].value = da;			//Data Param
    f.elements["id"].value = id;			//Page Param (Split Page forms only) / Callback script ID
    f.submit();
    return;
}

function q_OpenWindow(url, x, y)
{
	return window.open(url, "_blank", "location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,width="+x+",height="+y);
}

function q_ShowMessage(text)
{
	alert(text);
}

function q_ShowError()
{
	q_ShowMessage(f_querystring["fcErr"]);
}

function q_ShowDialog(text)
{
	return confirm(text);
}

function f_PlaySound(i, loop)
{
	q_PlaySound(i, loop);
}

function q_CheckSingleResponse(id)
{
	var c = (document.cookie+"").split("; ");
	for (var i=0; i<c.length; i++)
	{
		var s = c[i].split("=");
		if(s.length>1 && s[0]==id && s[1]=="1") return true;
	}
	return false;
}

function q_Randomize(arr, ib, ie) //array, begin-index, end-index
{
	for(var i=0; i<(ie-ib); i++)
	{
		var s0 = ib+Math.floor(Math.random()*(ie-ib));
		var s1 = ib+Math.floor(Math.random()*(ie-ib));
	
		//Swap indexes
		var o = arr[s0];
		arr[s0] = arr[s1];
		arr[s1] = o;
	}
}

function q_KeepAlive(b)
{
	//Try to create Ajax object
	var req = q_GetHTTPRequestObject();
    if(req)
    {
        if(b)
        {
            //Make call to server
		    req.onreadystatechange = 		
		    function()
		    {
		        //Don't do anything really, ignore response
			    if (req.readyState==4 && req.status == 200)
				    a=0;
		    };
			
		    req.open("GET", f_keepalive_url, true);
			req.send(null);
	    }
        
        //Set timer for next one
 		setTimeout("q_KeepAlive(true);", f_keepalive_mins*60000);
 	}
}


//---------------------------------------------------------
//-------------- Message Box Methods ----------------------
//---------------------------------------------------------


function q_ShowMsgBox(id)
{
	var x = f_page_x+(f_page_w-f_msgbox_w)/2-2;
	var y = f_page_y+(f_page_h-f_msgbox_h)/2;
	if(y<f_page_y+2) y=f_page_y+2;
	
	q_SetLeft(id, x);
	q_SetTop(id, y);
	q_SetBackCol(id, "ffffff");
	q_SetBorder(id, 2, "000000");
	q_SetVisible(id, true);
	
	q_ScrollIn(x, y, f_msgbox_w, f_msgbox_h);
}

function q_GetMsgBoxHTML(msg)
{
	var c = '<br>';
	if(f_page_h<100)c='';
	
	c = '<table cellspacing=0 cellpadding=0 border=0 width='+f_msgbox_w+'>'
	+	'<tr><td colspan=2 align=center valign=center bgcolor=#ffffff><table cellspacing=0 cellpadding=10 border=0><tr><td class=st_ql><center>'+c+msg+'<br>'+c+'</td></tr></table></td></tr>'
	+	'<tr><td colspan=2 bgcolor=#000000><img src="'+f_resources[0].src+'" width=1 height=1></td></tr>';

	if(!f_unbranded)
		c +=	'<tr><td bgcolor=#F3F3F3 class=st_ql2 align=right valign=center width='+(f_msgbox_w-25)+'>&nbsp;&nbsp;'+q_Texts[11]+'</td>'
			+	'<td bgcolor=#F3F3F3 width=25><a href="http://'+q_GetQuask()+'" target=_blank>'
			+   '<img src="'+f_resources[1].src+'" width=10 height=25 border=0>'
			+   '<img src="'+f_resources[2].src+'" width=2 height=25 border=0>'
			+   '<img src="'+f_resources[3].src+'" width=2 height=25 border=0>'
			+   '<img src="'+f_resources[4].src+'" width=2 height=25 border=0>'
			+   '<img src="'+f_resources[5].src+'" width=9 height=25 border=0>'
			+	'</a></td></tr>';
			
	c += '</table>';
	
	return c;
}



//---------------------------------------------------------
//---------------- Scripting Methods ----------------------
//---------------------------------------------------------


function q_RunScript(id, p, e) //p=Params e=Event Source
{
	//Don't do any scripts if no-script property or disabled
	//Don't do any scripts during Pre-Loading if in SplitMode and follow-up page
	if(id=="" || f_noscripts || f_scripts_disabled || f_preloading) return; //|| (f_splitpage && f_preloading && f_system["started"]>0)

	//Avoid endless loops, part 1
	if(arguments.length>2)
	{
		//Only if eventsource is specified
		if(f_currenteventsource==e) return null;
		f_currenteventsource = e;
	}
	
	//Get current page / control
	var r, current_page_id = "", current_control_id = "";
	if(f_current_page>=0) current_page_id = f_pages[f_current_page].id;
	if(f_current_control>=0) current_control_id = f_controls[f_current_control].id;

	//Avoid repeat endless loops, by checking stack
	for(i in f_scripts_stack)
		if(f_scripts_stack[i]==id)
			return null;

    //Maintain call stack
    f_scripts_stack.push(id);

	//Run the script
	r = q_RunScript2(id, current_control_id, current_page_id, p);
	
    //Maintain call stack
    f_scripts_stack.pop();
	
	//Avoid endless loops, part 2. Only if eventsource is specified
	if(arguments.length>2)
		f_currenteventsource = null;
	
	return r;
}

function q_RegisterFocus(i) //Called by each control when it gains focus (i=index)
{
	//Notify previous control that his has lost its focus
	if(f_current_control>=0 && f_current_control!=i && f_controls[f_current_control].OnFocusLost!=null)
		f_controls[f_current_control].OnFocusLost();
		
	//Remember new control
	f_current_control = i;
}

function q_CallScript() //Sub-function call from witin other script, felxible argument length
{
	var p = new Array();
	for(var i=0; i<arguments.length-1; i++) p[i]=arguments[i+1];
	return q_RunScript(arguments[0], p);
}

function q_Quit(b) //Used by scripting only
{
	f_HidePage();
	f_disableskin = true;		//Disable buttons from now on
	if(b==1)
	{
		//Hide Skin and Page Background
		if(f_skin)q_SetVisible("s_d", false);
		q_SetVisible("p_d", false);
	}
	if(b==2)window.close();
}

function q_SetFormProperty(n, v)
{
	//Override Form Properties
	switch(n)
	{
		case "readonly":
			f_readonly = q_IsTrue(v);
			break;
			
		case "forcefocus":
			f_forcefocus = q_IsTrue(v);
			break;
	}
}

function q_Debug(a, b, c)
{
    //Create object 1st time round
    if(f_debug_obj==null)
    {
		try
		{
    		if(window.ActiveXObject) 
				f_debug_obj = new ActiveXObject("FAVSDebug.JSDebugger");
		}
		catch(e)
		{
			f_debug_obj = null;
		}
	}

	//Make the call	
	if(f_debug_obj!=null)
         f_debug_obj.DebugCommand(a, b, q_GetDataXML(), c);
}

function q_IsTrue(v)
{
	v=(v+"").toLowerCase();
	return (v=="1"||v=="true");
}

function q_SetSystemProperty(n, v)
{
	f_system[n] = v;
}

function q_GetSystemProperty(n)
{
	return f_system[n];
}

function q_DateDiff(d1, d2, u, wd)
{
    d = (d2.getTime()-d1.getTime())/1000;
    
    switch(u)
    {            
        case 'y':
            d /= 365;
            
        case 'd':
            d /= 24;
        
        case 'h':
            d /= 60;

        case 'n':
            d /= 60;
            break;

        case 'w':
            d /= 604800;
            break;

        case 'm':
            d /= 2592000;
            break;
    }
    
    return Math.floor(d);
}

function q_DateAdd(d, n, u, wd)
{
    var r = new Date;
    r.setTime(d.getTime());
    switch(u)
    {
        case 's':
            r.setSeconds(r.getSeconds()+n);
            break;
            
        case 'n':
            r.setMinutes(r.getMinutes()+n);
            break;

        case 'h':
            r.setHours(r.getHours()+n);
            break;
            
        case 'd':
            r.setDate(r.getDate()+n);
            break;
            
        case 'w':
            r.setDate(r.getDate()+7*n);
            break;

        case 'm':
            r.setMonth(r.getMonth()+n);
            break;
            
        case 'y':
            r.setFullYear(r.getFullYear()+n);
            break;
    }
    
    return r;
}

function q_FormatDate(d, s)
{
    //Constants
    var m = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
	var w = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");

    //Day
    s = q_Replace(s, "%j", d.getDate()); //Day of month
    s = q_Replace(s, "%d", q_ForceDigits(d.getDate(), 2)); //Day of month (with leading 0)
    s = q_Replace(s, "%D", w[d.getDay()].substring(0, 3)); //Weekday (3 letters)
    s = q_Replace(s, "%l", w[d.getDay()]); //Weekday (full name)
    
    //Month
    s = q_Replace(s, "%F", m[d.getMonth()]); //Month (full name)
    s = q_Replace(s, "%m", q_ForceDigits(d.getMonth()+1, 2)); //Month (number with leading 0)
    s = q_Replace(s, "%M", m[d.getMonth()].substring(0, 3)); //Month (3 letters)
    s = q_Replace(s, "%n", d.getMonth()+1); //Month (number)
    
    //Year
    s = q_Replace(s, "%y", d.getYear()); //Year (2 digits)
    s = q_Replace(s, "%Y", d.getFullYear()); //Year (4 digits)
    
    //Time
    s = q_Replace(s, "%g", (d.getHours()%12==0)?12:(d.getHours()%12)); //Hours (1-12)
    s = q_Replace(s, "%G", d.getHours()); //Hours (0-23)
    s = q_Replace(s, "%h", q_ForceDigits((d.getHours()%12==0)?12:(d.getHours()%12), 2)); //Hours (01-12, 2 digits)
    s = q_Replace(s, "%H", q_ForceDigits(d.getHours(), 2)); //Hours (00-23, 2 digits)
    s = q_Replace(s, "%i", q_ForceDigits(d.getMinutes(), 2)); //Minutes (2 digits)
    s = q_Replace(s, "%s", q_ForceDigits(d.getSeconds(), 2)); //Seconds (2 digits)
    s = q_Replace(s, "%a", (d.getHours()>11)?"pm":"am"); //am or pm
    s = q_Replace(s, "%A", (d.getHours()>11)?"PM":"AM"); //AM or PM
    
    return s;
}

function q_DatabaseLookup(t, url, id, dx, fn) 
{
	//t=Type, url=URL, id=Callback Script, dx=Lookup Definition, fn=Fieldnames
	
	
	//--- Get fields data XML ---
	
	var f = "";
	if(fn!=null)
	{
		//Check each control's data
		for(var i=0; i<f_controls_n; i++)
		{
			//Get Data
			var d = f_controls[i].GetData();
			
			//Check each field
			if(d!=null)
				for(var j=0; j<d.length; j++)
				{
					//Check if it's one of the ones we need.
					for(var k=0; k<fn.length; k++)
						if(d[j].indexOf(fn[k]+"|")==0)
						{
							//Found match. Add it			
							f += q_GetFieldXMLTag(d[j], null);
							break;
						}
				}
		}
	}
	f = q_GetParentXMLTag("<fields>"+f+"</fields>");

	//Send it 
	if(t==0)
	{
		//Background
		var d = new Array(3);
		d[0] = Array("id", id);
		d[1] = Array("lookup", dx);
		d[2] = Array("data", f);
		q_GetURL(url, null, id, d);
	}
	else
	{
		//Pop-Up
		var w = q_OpenWindow("", 600, 500);
		if (w!=null && w!="")
		{
			w.document.write('<html><body><form action="'+url+'" method=POST>'
						+	q_GetHiddenInputHTML("id", id)
						+	q_GetHiddenInputHTML("lookup", dx)
						+	q_GetHiddenInputHTML("data", f)
						+	'</form></body></html>');
			w.document.forms[0].submit();
		}
	}
}

//SQLServerLookup Helper 
function q_GetHiddenInputHTML(n, v) //Name and Value
{
	//Value: Replace ' with escape characters
	n = q_Replace(n, "'", "\\x27");
	v = q_Replace(v, "'", "\\x27");

	return "<input type=hidden name='"+n+"' value='"+q_XMLEncode(v)+"'>";
}


function q_GetURL(url, p, id, d)	//p=QueryString param, id = Callback Script, d=POST data (as Array)
{
	if(!f_preview)
	{
		//Handle additional URL parameter
		if(p!=null && p.length>0)
			url = q_AddParamChar(url) + "param=" + q_Escape(p);

		//Try to create Ajax object
		var req = q_GetHTTPRequestObject();
		
		//If object exists, do Ajax, otherwise Pop-up method
		if(req) 
		{
			//Yes, do Ajax
			
			//Define callback function
			req.onreadystatechange = 		
			function()
			{
				if (req.readyState==4 && req.status == 200)
					q_Callback(id, req.responseText);
			};
			
			//Compile POST variables
			var pv = "";
			if(d && d.length)
				for(var i=0; i<d.length; i++)
				{
					if(pv!="") pv += "&";
					pv += q_Escape(d[i][0]) + "=" + q_Escape(d[i][1]);
				}
				
			//Make the call
			req.open("POST", url, true);
			req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
			req.send(pv);
		}
		else
		{
			//Open pop-up window
			q_OpenWindow(q_AddParamChar(f_servercomm_url)+"url="+q_Escape(url)+"&id="+q_Escape(id), 300, 100);
		}
	}
}

//General Callback (e.g. from SQLServerLookup)
function q_Callback(id, v)
{
	var p = new Array();
	p[0] = q_Unescape(v);
	q_RunScript(""+id, p)
}

//GetURL Callback (should be replaced by above, for back-campatibility)
function q_GetURL2(id, v)
{
	q_Callback(id, v);
}

function q_GetControlByID(id)
{
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].id==id) return f_controls[i];
		
	//Not found
	return null;
}

function q_GetControlByTag(t)
{
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].tag==t) return f_controls[i];
		
	//Not found
	return null;
}

function q_GetPageByID(id)
{
	//Try ids first
	for(var i=0; i<f_pages_n; i++)
		if(f_pages[i].id==id) return f_pages[i];
		
	//Also try name
	for(var i=0; i<f_pages_n; i++)
		if(f_pages[i].name==id) return f_pages[i];

	//Not found
	return null;
}

function q_OnResize()
{
	//If relative positionned form, move skin and page background to new position
	if(!f_absolute_pos)
		q_RePositionForm();
}

//WorkFlow function (type, param_names, params), e.g. q_WorkFlow("notify", "who,person,action,param,login", "me", ...)
function q_WorkFlow()
{
	var n = arguments[1].toString().split(",");
	f_additional_data += '<workflow type="' + arguments[0] + '"';
	for(var i=2; i<arguments.length; i++) f_additional_data += ' '+n[i-2]+'="'+q_XMLEncode(arguments[i])+'"';
	f_additional_data += ' />';
}

//String Validation
function q_IsValidEmail(s)
{
	var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(s);
}

function q_IsValidURL(s)
{
	var re = /^((http|https|ftp)\:\/\/)?[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?\/?([a-zA-Z0-9\-\._~\\\/\?\,\'+&%\$#\=~])*$/;
    return re.test(s);
}

function q_IsAlpha(s)
{
	var re = /^[\sa-zA-Z]*$/;
    return re.test(s);
}

function q_IsAlphaNumeric(s)
{
	var re = /^[\sa-zA-Z0-9]*$/;
    return re.test(s);
}

function q_IsUpper(s)
{
	s=""+s;
	return (s.toUpperCase()==s);
}

function q_IsLower(s)
{
	s=""+s;
	return (s.toLowerCase()==s);
}


//---------------------------------------------------------
//----------------------- Helpers -------------------------
//---------------------------------------------------------


function q_GetQuask() //Returns the Q-logo click link (without http://)
{
	var rr = "ask";
	var r = "";
	for(var i=0; i<3; i++)r+="w";
	r+=".qu"+rr;
	r=r+".co";
	return r+"m/form";
}

function q_XMLEncode(s)
{
	s = "" + s;
	
	s = q_Replace(s, "&", "@amp;");
	s = q_Replace(s, "@amp;", "&amp;");
	s = q_Replace(s, "<", "&lt;");
	s = q_Replace(s, ">", "&gt;");
	s = q_Replace(s, "+", "&#43;");
	s = q_Replace(s, "'", "&#39;");
	s = q_Replace(s, '"', "&quot;");
	
	var sout = "";
	for(var i=0; i<s.length; i++)
	{
		var v=s.charCodeAt(i);
		if(v>0)
		{
		    if(v<32||v>127)
			    sout += "&#" + v + ";";
		    else
			    sout += s.charAt(i);
	    }
	}
	
	return sout;
}

function q_Unescape(s)
{
	s=unescape(s);
	s=q_Replace(s, "+", " ");
	return s;
}

function q_Escape(s)
{
	s=escape(s);
	s=q_Replace(s, " ", "+");
	return s;
}

function q_Replace(s, a, b)
{
	while(s.indexOf(a)>=0) s=s.replace(a, b);
	return s;
}

function q_StupidDecode(s)
{
	var o = "";
	s=s+"";
	var l = s.length;
	
	//Char by char (in revers)
	for(var i=0; i<l; i++)
	{
		var c = s.charCodeAt(l-1-i);
		if(c>=32 && c<=126) c = 158-c;
		o += String.fromCharCode(c);
	}

	return o;
}

function q_QueryStringDecode(s, seed)
{
	var out="";
	for(var i=0; i<(s.length/2); i++)
	{
		var char1 = s.charCodeAt(i*2) - 97;
		var char2 = s.charCodeAt(i*2+1) - 97;
		
		var ch = (char1*16 + char2 - seed - i) & 255;
		
		out = out + String.fromCharCode(ch);
	}
	
	if(out.charAt(out.length-1)!='q') return "";
	else return out.substring(0, out.length-1);
}

function q_GetIndex(arr, v)
{
	for(var i=0; i<arr.length; i++)
		if(arr[i]==v) return i;
		
	//Not found
	return -1;
}

function q_IsArray(o)
{
    return (o.constructor.toString().indexOf("Array")!=-1);
}

function q_AddParamChar(u) //Adds ? or & to end of url
{
	if(u.indexOf("?")<0) u+="?";
	if(u.charAt(u.length-1)!="?" && u.charAt(u.length-1)!="&") u+="&";
	return u;
}

function q_Trim(s)
{
	//Remove leading spaces
	while(s.charAt(0)==' ') s=s.substring(1);
	
	//Remove ending spaces
	if(s.length==0) return s;
	while(s.charAt(s.length-1)==' ') s=s.substring(0, s.length-1);
	
	return s;
}

function q_HandleNumeric(v) //Takes a string and returns either a string or numeric type of the same
{	
	if(v==null || v=="") return v;
	
	//If startes with 0 but not followed by decimal, treat as string (e.g. zip "09232")
	if(v.charAt(0)=='0' && v.length>1 && v.charAt(1)!='.' && v.charAt(1)!=',') 
		return v;
	
	//Avoid "1E02=100" bug
	if(v.indexOf('e')>=0 || v.indexOf('E')>=0)
		return v;
		
	//If numeric, return as numeric type
	if(!isNaN(1*v)) return parseFloat(v);
	else return v;
}

function q_ForceDigits(s, l)
{
	while((s+"").length<l) s = "0" + s;
	return s;
}

function q_GetHTTPRequestObject()
{
	if(window.XMLHttpRequest) 
		return new XMLHttpRequest();
		
	if(window.ActiveXObject) 
		return new ActiveXObject("Microsoft.XMLHTTP");
				
    //None of the above works
    return null;
}


//--- CSS Helpers -----

function q_GetFontCSS(f)
{
	var s=f_fonts[parseInt(f)].split("|");
	var css="font-size: "+s[0]+"; font-family: "+s[1]+";";
	if(s[2]&1) css=css+" font-weight: bold;";
	if(s[2]&2) css=css+" font-style: italic;";
	if(s[2]&4) css=css+" text-decoration: underline;";
	return css;
}

function q_GetDisabledAttribute(b)
{
    return b?'':' disabled="disabled"';
}

//Get valign= and align= html
function q_GetAlignHTML(a)
{
	var c;
	
	switch(a & 3)
	{
	case 1:		c = "align=left ";		break;
	case 2:		c = "align=right ";		break;
	default:	c = "align=center ";	break;
	}
		
	switch((a >> 2) & 3)
	{
	case 1:		return c + "valign=top ";
	case 2:		return c + "valign=bottom ";
	default:	return c + "valign=center ";
	}
}

//Netscape 4.x doesn't support pixel width/height in <input text> and <textarea>
//It uses size (in chars) instead, this estimates a corresponding charwidth
function q_GetCharSize(f, w)	{return w/parseInt((s=f_fonts[parseInt(f)].split("|"))[0])*1.2;}

//Returns position (x,y) of an image (<img id="xxx" >) within the whole HTML page
function q_GetImagePagePos(id)
{
	// Defaults
	var x=0, y=0;

	var o;
	if(q_bDOM2) o = document.getElementById(id);
	if(q_bIE) o = document.all[id];
	while(o && o.tagName != "BODY" && o.tagName != "HTML") 
	{	
		x += o.offsetLeft;
		y += o.offsetTop;
		o = o.offsetParent;
	}
	
	//Fine tuning
	if(q_bIE && navigator.userAgent.indexOf("Opera")<0) {x++;y++};
	if(q_bDOM2 && navigator.userAgent.indexOf("Firebird")<0) {x+=2;y+=2};
	
	//Return
	return  Array(x,y);
} 



//---------------------------------------------------------
//------------------- Event Switchboard  ------------------
//---------------------------------------------------------


function q_InitEvents()
{
	q_CaptureEvents();
	document.onmousedown = q_OnMouseDown;
	document.onmousemove = null;
	document.onmouseup = null;
}

function q_OnMouseDown(e)
{
	//Get Name/ID of element that raised event
	var n = "";
	var t = q_GetEventTarget(e);
	if(t.name!=null) n=t.name;		//Check name if image
	else if(t.id!=null) n=t.id;		//Check id if other element
	
	//--- Is it from a Control? -> Dispatch Event to right control
	if (n.indexOf("i_")==0)
	{
		//Get index
		j = parseInt(n.substring(2));
		
		//Register focus
		q_RegisterFocus(j);
		
		//Dispatch Event
		if(f_controls[j].OnMouseDown!=null)
			return f_controls[j].OnMouseDown(q_GetEventX(e)-f_page_x, q_GetEventY(e)-f_page_y, n);
	}
	
	//--- Is it from a skin button ? ---	
	if (n.indexOf("sb_")==0) return f_SkinButtonMouseDown(q_GetEventX(e), q_GetEventY(e), parseInt(n.substring(3)));
	
	return true;
}

function q_OnMouseMove(e)
{
	//Dispatch Event to control that has captured the mouse event
	if(f_capturing_control>=0) return f_controls[f_capturing_control].OnMouseMove(q_GetEventX(e)-f_page_x, q_GetEventY(e)-f_page_y);
	else if(f_capturing_control==-9) return f_SkinButtonMouseMove(q_GetEventX(e), q_GetEventY(e));
	else return true;
}

function q_OnMouseUp(e)
{
	//Dispatch Event to control that has captured the mouse event
	if(f_capturing_control>=0) return f_controls[f_capturing_control].OnMouseUp(q_GetEventX(e)-f_page_x, q_GetEventY(e)-f_page_y);
	else if(f_capturing_control==-9) return f_SkinButtonMouseUp(q_GetEventX(e), q_GetEventY(e));
	else return true;
}

function q_CaptureMouse(index)
{
	//Send "LoseMouse" event to previous "capturor"
	if(f_capturing_control>=0 && f_controls[f_capturing_control].OnLoseMouse!=null)
			f_controls[f_capturing_control].OnLoseMouse();

	//Set new capturing control
	f_capturing_control=index; //Special case: -9 = Skin Button
	
	document.onmousemove = q_OnMouseMove;
	document.onmouseup = q_OnMouseUp;
}

function q_ReleaseMouse()
{
	f_capturing_control=-1;
	
	document.onmousemove = null;
	document.onmouseup = null;
}

function q_OnKeyPress(e, index)	//This is must be called by "onkeypress='q_OnKeyPress(event, 123);'" attribute
{
	if(f_controls[index].OnKeyPress!=null)
		return f_controls[index].OnKeyPress(q_GetEventKey(e), q_GetEventTarget(e));
}

function q_OnKeyRelease(e, index)	//This is must be called by "onkeyup='q_OnKeyRelease(event, 123);'" attribute
{
	if(f_controls[index].OnKeyRelease!=null)
		return f_controls[index].OnKeyRelease(q_GetEventKey(e), q_GetEventTarget(e));
}

function q_OnChange(e, index)	//This is must be called by "onchange='return q_OnChange(event, 123);'" attribute
{
	if(f_controls[index].OnChange!=null)
		return f_controls[index].OnChange(q_GetEventTarget(e));
}

function q_OnTimer(index)		//This must be called by "setTimeout("q_OnTimer(index, 1000);")"
{
	if(f_controls[index].OnTimer!=null)
		return f_controls[index].OnTimer();
}

function q_OnEffectTimer(index)		//This must be called by "setTimeout("q_OnEffectTimer(index, 1000);")"
{
	return f_controls[index].OnEffectTimer();
}

function q_OnMouseDownEx(e, index)	//This is must be called by "onmousedown='q_OnMouseDown(event, 123);'" attribute
{
	q_RegisterFocus(index);

	if(f_controls[index].OnMouseDown!=null)
		return f_controls[index].OnMouseDown(q_GetEventX(e), q_GetEventY(e));
}

function q_OnMouseOver(e, index)	//This is must be called by "onmouseover='q_OnMouseOver(event, 123);'" attribute
{
	if(f_controls[index].OnMouseOver!=null)
		return f_controls[index].OnMouseOver(q_GetEventX(e), q_GetEventY(e), q_GetEventTarget(e));
}

function q_OnMouseOut(e, index)	//This is must be called by "onmouseout='q_OnMouseOut(event, 123);'" attribute
{
	if(f_controls[index].OnMouseOut!=null)
		return f_controls[index].OnMouseOut(q_GetEventX(e), q_GetEventY(e), q_GetEventTarget(e));
}

function q_OnFocus(e, index)	//This is must be called by "onfocus='q_OnFocus(event, 123);'" attribute
{
	q_RegisterFocus(index);
	
	if(f_controls[index].OnFocus!=null)
		return f_controls[index].OnFocus(q_GetEventX(e), q_GetEventY(e), q_GetEventTarget(e));
}

function q_OnBlur(e, index)	//This is must be called by "onBlur='q_OnBlur(event, 123);'" attribute
{
	if(f_controls[index].OnBlur!=null)
		return f_controls[index].OnBlur();
}

function q_OnUpload(id, filename)	//This is must be called by outside window
{
	if(q_GetControlByID(id).OnUpload!=null)
		return q_GetControlByID(id).OnUpload(filename);
}


//--- Form Event Triggers ---

function f_OnFormStart()
{
	//Event Trigger (Form OnLoad)
	if(f_events!=0)
    	q_RunScript(f_events[0]);

	//Check each control if it wants to handle this
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].OnFormStart!=null)
			f_controls[i].OnFormStart();			
}

function f_OnPageFocus(pageindex)
{
	//Scripting Triggers
	if(f_pages[pageindex].events!=0)
    	q_RunScript(f_pages[pageindex].events[0]);
	
	//Check each control in this page if it wants to handle this
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].page==pageindex && f_controls[i].OnPageFocus!=null)
			f_controls[i].OnPageFocus();
}

function f_OnPageBlur(pageindex)
{
	//Scripting Triggers
	if(f_pages[pageindex].events!=0)
    	q_RunScript(f_pages[pageindex].events[1]);
	
	//Check each control in this page if it wants to handle this
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].page==pageindex && f_controls[i].OnPageBlur!=null)
			f_controls[i].OnPageBlur();
}



//---------------------------------------------------------
//---------------- Control Panel (Skin)  ------------------
//---------------------------------------------------------


function f_SkinButtonMouseDown(eX, eY, id)
{	
	//Is it Logo?
	if(id==9)
	{
		q_ShowURL("http://"+q_GetQuask());
		return false;
	}
	
	//Dont do it after send was pressed
	if(f_disableskin) return false;
	
	//Remember button and pos
	f_pressed_skinbutton = id;
	f_pressed_skinbutton_x = eX;
	f_pressed_skinbutton_y = eY;
	
	//Graphical "Pressed" Effect
	q_GetImage("s_d", "sb_"+id).src = f_skin_but_p[id].src;

	q_CaptureMouse(-9);		
	return false;
}


function f_SkinButtonMouseMove(eX, eY)
{
	//If moved outside, change pic to "Normal", if inside, change pic to "Pressed"
	if(Math.abs(eX-f_pressed_skinbutton_x)<f_skin_w && Math.abs(eY-f_pressed_skinbutton_y)<f_skin_h/2)
		q_GetImage("s_d", "sb_"+f_pressed_skinbutton).src = f_skin_but_p[f_pressed_skinbutton].src;
	else
		q_GetImage("s_d", "sb_"+f_pressed_skinbutton).src = f_skin_but_n[f_pressed_skinbutton].src;
	
	return false;
}


function f_SkinButtonMouseUp(eX, eY)
{
	//Change pic to "Normal"
	q_GetImage("s_d", "sb_"+f_pressed_skinbutton).src = f_skin_but_n[f_pressed_skinbutton].src;
	q_ReleaseMouse();
	
	//If not moved outside button, do action
	if(Math.abs(eX-f_pressed_skinbutton_x)<f_skin_w && Math.abs(eY-f_pressed_skinbutton_y)<f_skin_h/2)
	{
		//Do Action
		switch(f_pressed_skinbutton)
		{
		case 0:		q_SendData();	break;	//Send
		case 1:		q_ResetData();	break;	//Reset
		case 2:		q_Print();		break;	//Print
		case 3:		q_PrevPage();	break;	//Page Back
		case 4: 	q_NextPage();	break;	//Page Forward
		}
	}
	
	return false;
}

function q_SkinPageComboChanged()
{
	//Dont do it after send was pressed
	if(f_disableskin) return false;
	
	f_GoToPage(parseInt(q_GetSelectedValue("s_d", "p_cb")));
}




//=========================================================
//=================== PAGE OBJECT =========================
//=========================================================


//--- Constructor ---

function q_page(i, p)
{
	this.index = i;
	this.color = p[0];	    	//Background-color of page
	this.name = p[1];		    //Name of page
	this.id = p[2];		    	//ID of page
	this.randomize = (p[3]>0);	//Randomize? true/false
	this.events = p[4];		    //Event triggers (Array)

	this.enabled = true;
	this.readonly = false;
	
	this.SetBackCol = q_page_SetBackCol;
	this.GetBackCol = q_page_GetBackCol;
	
	this.SetEnabled = q_page_SetEnabled;
	this.GetEnabled = q_page_GetEnabled;
	
	this.SetReadOnly = q_page_SetReadOnly;
	this.GetReadOnly = q_page_GetReadOnly;
	
	this.GoTo = q_page_GoTo;
}

function q_page_SetEnabled(e, b)
{
	this.enabled = e;
	
	//Set it on all controls in this page
	for(var i=0; i<f_controls_n; i++)
	{
		if(f_controls[i].page == this.index && ((b==true) || f_controls[i].type!=12))
			f_controls[i].SetEnabled(e);			
	}
}

function q_page_GetEnabled()
{
	return this.enabled;
}

function q_page_SetReadOnly(r)
{
	this.readonly = r;
	
	//Set it on all controls in this page
	for(var i=0; i<f_controls_n; i++)
		if(f_controls[i].page == this.index) f_controls[i].SetReadOnly(r);
}

function q_page_GetReadOnly()
{
	return this.readonly;
}

function q_page_SetBackCol(c)
{
	//Store
	this.color = c;
	
	//If this page is currently showing, update color on screen
	if(f_current_page==this.index)
		q_SetBackCol("p_d", this.color);
}

function q_page_GetBackCol()
{
	return this.color;
}

function q_page_GoTo()
{
	f_GoToPage(this.index);
}



//=========================================================
//================= CONTROLS OBJECTS ======================
//=========================================================


//--- Constructor Dispatcher ---

function q_ctrl(index, args)
{
	switch(args[0]) //First field contains type of control
	{
	case 1:		return new q_la(index, args);	//Text Label
	case 2:		return new q_tx(index, args);	//Text Input
	case 3:		return new q_nu(index, args);	//Numeric Input
	case 5:		return new q_li(index, args);	//List Selection
	case 6:		return new q_pi(index, args);	//Picture Label
	case 7:		return new q_ch(index, args);	//Checkboxes
	case 9:		return new q_dd(index, args);	//Drop-Down Selection
	case 10: 	return new q_dt(index, args);	//Date/Time
	case 11:	return new q_ma(index, args);	//Matrix
	case 12: 	return new q_bu(index, args);	//Button
	case 13: 	return new q_em(index, args);	//Emoticon
	case 14: 	return new q_so(index, args);	//Sound
	case 15: 	return new q_ra(index, args);	//Ranking
	case 16: 	return new q_ti(index, args);	//Timer
	case 17: 	return new q_up(index, args);	//Upload
	case 18: 	return new q_ta(index, args);	//Table Input
	case 98: 	return new q_gh(index, args);	//Ghost Object (Split Page forms only)
	case 99: 	return new q_pg(index, args);	//Picture Grid
	default:	return null;
	}
}



//---------------------------------------------------------
//---------------- Control "Base class"  ------------------
//---------------------------------------------------------


//--- Constructor ---

function q_bc_Constr(o, index, args)
{
	//Store base properties
	o.index = index;		    //HTML internal numbering (Ctrls[index])
	o.type = args[0];		    //Type of control
	o.id = args[1];		    	//ID
	o.tag = args[2];		    //Tag for data
	o.required = (args[3]>0);	//Is this control obligatory?
	o.page = args[4];		    //Page number
	o.tab = args[5];		    //Tab order
	
	//Ghost doesn't have to following properties
	if(o.type!=98)
	{
		o.x = args[6];			//Initial position of object (relative to Skin)
		o.y = args[7];			//Initial position of object (relative to Skin)
		o.width = args[8];		//Width of object
		o.height = args[9];		//Height of object
		o.frame = args[10];		//Size of frame
		o.framepic = args[11];	//Picture representing the frame
		o.padding = args[12];	//Size of padding
		o.backcol = args[13];	//Initial background color of object
		o.forecol = args[14];	//Foreground color of object
		o.zorder = args[15];	//Z-order
		o.font = args[16];		//Index of first font
	}
	else
	{
		//Ghost all 0's
		o.x = o.y = o.width = o.height = o.frame = o.framepic = o.padding = o.zorder = o.font = 0;
		o.backcol = o.forecol = "000000";
	}

	//Derived properties
	o.cwidth = o.width-2*o.padding-2*o.frame;	//Size of "client" area of control
	o.cheight = o.height-2*o.padding-2*o.frame;	//Size of "client" area of control
	
	//Default properties
	o.created = false;       //Is set to true once .Create() method is called
	o.visible = true;		//Is control visible in form (actual visibility depends on whether this page is shown)
	o.showing = false;		//Initially not showing (shows only when page is displayed)
	o.enabled = true;		//Enabled/Disable (showing but cannot be used)
	o.readonly = false;		//Is shown but cannot be changed
	o.shaded = false;		//Shaded/Normal
	o.effect = -1;			//1==Fade In, 2==Fade Out, 3...
	o.effectstep = 0;		//Counter in effect timer
	o.effectdirection = 0;	//Moving in ...
	o.effectend_x = 0;		//End postion if moving
	o.effectend_y = 0;		//End postion if moving
	o.flashing = 0;			//Flashing Steps to countdown (for state info only)
	o.transparency = 100;   //100% (default)
	
	//Property Changes log
	o.changed = 0;			//Keeps track of any changes of properties. Bitfield:
	//1=XPos, 2=YPos; 4=ZOrder; 8=BackCol; 16=Enabled; 32=ReadOnly; 64=Shaded; 128=Visible
	//256=Tag; 512=Transparency; 1024=Answers; 2048=Source (Pic obj.); 4096=Caption (Label obj.)
	//8192=Untouched, 16384=Last Selected, 32768=Flashing
	
	//Baseclass Methods

	o.Create = null;					    //Write HTML (Must always be overridden)
	o.Show = q_bc_Show;					    //Show (when page is shown)

    o.CreateMainDiv = q_bc_CreateMainDiv;
    o.CreateDiv = q_bc_CreateDiv;

	o.GetX = q_bc_GetX;	
	o.SetX = q_bc_SetX;
	o.GetY = q_bc_GetY;
	o.SetY = q_bc_SetY;
	o.GetZOrder = q_bc_GetZOrder;
	o.SetZOrder = q_bc_SetZOrder;

	o.SetBackCol = q_bc_SetBackCol;
	o.GetBackCol = q_bc_GetBackCol;
		
	o.GetEnabled = q_bc_GetEnabled;
	o.SetEnabled = q_bc_SetEnabled;
	o.GetReadOnly = q_bc_GetReadOnly;
	o.SetReadOnly = q_bc_SetReadOnly;
	o.GetShaded = q_bc_GetShaded;
	o.SetShaded = q_bc_SetShaded;
	o.GetShadedColor = q_bc_GetShadedColor;     //Helper for SetShaded/SetBackground
	o.GetVisible = q_bc_GetVisible;
	o.SetVisible = q_bc_SetVisible;
	o.GetTag = q_bc_GetTag;
	o.SetTag = q_bc_SetTag;
	o.SetTransparency = q_bc_SetTransparency;
	o.SetMode = q_bc_SetMode;

	o.CheckObligatory = q_bc_CheckObligatory;
	o.CheckValid = q_bc_DoNothing;				//Used by Text Input only
	o.GetData = q_bc_GetData;
	o.SetData = q_bc_SetData;
	o.ResetData = q_bc_ResetProperties;			//(Shortcut)
	o.ResetProperties = q_bc_ResetProperties;	//Called from within <obj>_ResetData
	o.CopyData = q_bc_CopyData;					//Table Input Only
	o.TriggerEvent = q_bc_TriggerEvent;
	
	o.GetValue = q_bc_GetScriptingValue;		//Used by Scripting only
	o.SetValue = q_bc_SetScriptingValue;		//Used by Scripting only
	o.GetState = q_bc_DoNothing;				//Used by Scripting only
	o.SetState = q_bc_DoNothing;				//Used by Scripting only
	o.GetValueCaption = q_bc_DoNothing;			//Used by Scripting only
	o.SetAnswers = q_bc_DoNothing;				//Drop-Downn & List only
	o.SetSource = q_bc_DoNothing;				//Picture Only
	o.SetUntouched = q_bc_DoNothing;			//Ghost Only
	o.GetSum = q_bc_DoNothing;					//Table Input Only
	o.SetDownloadURL = q_bc_DoNothing;			//Upload only

	o.GoTo = q_bc_GoTo;							//Go to this object
	o.StartFlashing = q_bc_StartFlashing;		//Flashing objects
	o.ApplyEffect = q_bc_ApplyEffect;			//Fade In etc...
	o.OnEffectTimer = q_bc_OnEffectTimer;		//Fade In etc...
	o.StartTimer = null;						//Only implemented by Timer object
	o.SetCaption = null;						//Only implemented by Label object

	//Methods to access/manipultate HTML elements in object's MainDiv
	o.GetHTMLForm = q_bc_GetHTMLForm;
	o.GetHTMLElement = q_bc_GetHTMLElement;
	o.GetHTMLElementValue = q_bc_GetHTMLElementValue;
	o.SetHTMLElementValue = q_bc_SetHTMLElementValue;
	o.GetHTMLElementSelectedIndex = q_bc_GetHTMLElementSelectedIndex;
	o.SetHTMLElementSelectedIndex = q_bc_SetHTMLElementSelectedIndex;
	o.GetHTMLElementSelectedValue = q_bc_GetHTMLElementSelectedValue;
	o.SetHTMLElementSelectedValue = q_bc_SetHTMLElementSelectedValue;
	o.GetHTMLElementOptions = q_bc_GetHTMLElementOptions;
	o.SetHTMLMainDivBackCol = q_bc_SetHTMLMainDivBackCol;
	o.SetHTMLElementBackCol = q_bc_SetHTMLElementBackCol;
	o.GetHTMLImage = q_bc_GetHTMLImage;
	o.GetHTMLElementCaretPos = q_bc_GetHTMLElementCaretPos;
	o.SetHTMLElementCaretPos = q_bc_SetHTMLElementCaretPos;

	//Event handling methods
	o.OnMouseDown=null;			//Doesn't need to be implemented
	o.OnMouseMove=null;
	o.OnMouseUp=null;
	o.OnKeyPress=null;			//Text & Numeric Input
	o.OnKeyRelease=null;		//Only used by Numeric
	o.OnChange=null;
	o.OnTimer=null;				//Only implemented by Timer object
	o.OnPageFocus=null;			//Only implemented by Timer and Sound objects
	o.OnPageBlur=null;			//Only implemented by Timer object
	o.OnFormStart=null;			//Only implemented by Timer object
	o.OnMouseOver=null;			//Only implemented by Labels, Sound and Picture Grid object
	o.OnMouseOut=null;			// "
	o.OnLoseMouse=null;			//Only implemented by Picture Grid
	o.OnFocus=null;				//Implemented by Text, Combo etc. for Scripting
	o.OnFocusLost=null;			//Only implemented by Date/Time
	o.OnUpload=null;			//Implemented by Upload only
	
	return (o.type==98)?6:17;	//Returns number of baseclass properties (Ghost has only 6)
}


//---- Base class Methods (can be overridden by each control ----



//--- Create HTML of object

function q_bc_CreateMainDiv(c, f) //c=Contents, f=Do Form?
{
    var h = "";
    
    //-- Add additional HTML around it ---
    
	//Does it require a <form> ?
	if(f)
	    h += '<form name="f_i_' + this.index + '_d" style="margin: 0px; padding 0px" method="post" onsubmit="return false;">';

    //Put it into <table> (for alignment)
	h += '<table cellspacing=0 cellpadding=0 border=0 width=' + this.width + ' height=' + this.height + '>';
	
    //Put it all into a <td>, centered
	h +=	'<tr><td width='+this.width+' height='+this.height+' align="center" valign="center"';

    //Handle frame style
	if(this.frame>0 && this.framepic>=0)
	    h += ' style="background-image: url(' + f_resources[this.framepic].src + '); background-repeat: no-repeat"';
	
	h +=	'>'	+ c + '</td></tr>';
	
    //End table
    h += '</table>';
    
   	//End form
	if(f)
	    h += '</form>';


    //--- Create Div layer --

    var n = document.createElement('div');
    var s = n.style;
    s.position = 'absolute';
    s.visibility = 'hidden';
    s.left = this.x + 'px';
    s.top = this.y + 'px';
    s.width = this.width + 'px';
    //s.height = this.height + 'px';
    s.zIndex = 10 + (this.zorder*10);
    if(this.GetShadedColor(this.backcol) != "") s.backgroundColor = "#" + this.GetShadedColor(this.backcol);
    n.setAttribute('id', 'i_' + this.index + '_d');
    n.innerHTML = h;

    //Add it to "Page" layer
    document.getElementById('p_d').appendChild(n);
    
    //Set Created Flag
    this.created = true;
}

function q_bc_CreateDiv(id, x, y, z, c, bg, b, w, h) //x,y,z=Position, c=Contents, bg=Background Color, b=Border, w=Width, h=Height
{
    //--- Create Div layer --

    var n = document.createElement('div');
    var s = n.style;
    s.position = 'absolute';
    s.visibility = 'hidden';
    s.left = x + 'px';
    s.top = y + 'px';
    s.zIndex = z;
    if(bg && bg!="") s.backgroundColor = "#" + bg;
    if(b && b!="") s.border = b;
    if(w) s.width = w;
    if(h && h>0) { s.overflow = 'hidden'; s.height = h; };
    n.setAttribute('id', id);
    n.innerHTML = c;

    //Add it to "Page" layer
    document.getElementById('p_d').appendChild(n);
}

//--- X/Y/Z Postion Methods

function q_bc_GetX()
{
	return this.x;
}

function q_bc_GetY()
{
	return this.y;
}

function q_bc_SetX(x)
{
	if(x>=0 && x<=f_page_w-this.width)
	{
		this.x = x;
		if(this.created)
    		q_SetLeft("i_"+this.index+"_d", x);

		this.changed |= 1;
	}
}

function q_bc_SetY(y)
{
	if(y>=0 && y<=f_page_h-this.height)
	{
		this.y = y;
		if(this.created)
    		q_SetTop("i_"+this.index+"_d", y);

		this.changed |= 2;
	}
}

function q_bc_GetZOrder()
{
	return this.zorder;
}

function q_bc_SetZOrder(z)
{
	if(z>=0 && z<3276)
	{
		this.zorder = z;
		
		if(this.created)
    		q_SetZOrder("i_"+this.index+"_d", 10+z*10);

        //Log
		this.changed |= 4;
	}
}

function q_bc_SetBackCol(c)
{
	this.backcol = c;
	
	if(this.created)
    	this.SetHTMLMainDivBackCol(this.GetShadedColor(c));
	
    //Log
	this.changed |= 8;
}

function q_bc_GetBackCol()
{
	return this.backcol;
}

function q_bc_StartFlashing(n) //TO DO Created?
{
	//Is there already flashing going on?
	if(f_flashing_controls==null)
	{
		//No. Start a new flash
		f_flashing_controls = new Array(1);
		f_flashing_controls[0] = this;
		
		//Get timer going...
		setTimeout("q_Flashing();", 300);		
	}
	else
	{
		//Yes. Simply add this control to it
		f_flashing_controls[f_flashing_controls.length] = this;		
	}

	//Set/Reset Steps
	f_flashing_steps = n;

	//State Info
	this.changed |= 32768;
	this.flashing = n;	
}

function q_bc_ApplyEffect(id, param1, param2) //TO DO: Created
{
	//If previous is still going, end it
	if(this.effect>0)
	{
		this.SetX(this.effectend_x);
		this.SetY(this.effectend_y);
	}
	
	//Start
	this.effect = id;
	this.effectstep = 0;
	this.effectend_x = this.GetX();
	this.effectend_y = this.GetY();
	this.effectmaxstep = param1*10;
	this.effectdirection = param2;

	//Start with transparent
	if(id==1) this.SetTransparency(0);
	
	//Make sure it is visible
	this.SetVisible(true);
	
	//Set Transparency only
	if(id==5) this.SetTransparency(param1);
	
	//Start Timer
	else this.OnEffectTimer();
}

function q_bc_OnEffectTimer()
{
	if(this.effect>0)
	{
		this.effectstep++;
		if(this.effectstep>this.effectmaxstep)
		{
			//End Reached
			
			//Clean Up
			switch(this.effect)
			{
			case 2: //Fade Out
				this.SetVisible(false);
				//No break..
				
			case 1: //Fade In
				this.SetTransparency(100);
				break;
				
			case 4: //Move Out
				this.SetVisible(false);
				//No break..

			case 3: //Move In
				this.SetTransparency(100);
				this.SetX(this.effectend_x);
				this.SetY(this.effectend_y);
				break;
			}
			
			//Default
			this.effect = -1;
		}
		else
		{
			//Next Step
			
			var r = this.effectstep/this.effectmaxstep;
			
			switch(this.effect)
			{
			case 2: //Fade Out
				r = 1-r;
				//No break...
				
			case 1: //Fade In
				this.SetTransparency(100*r);
				break;
				
			case 4: //Move Out
				r = 1-r;
				//No break...
			
			case 3: //Move In
				this.SetTransparency(100*r);
				if(this.effectdirection==0) //Top
					this.SetY(this.effectend_y*r);
				if(this.effectdirection==1) //Right
					this.SetX(f_page_w-this.width-(f_page_w-this.effectend_x-this.width)*r);
				if(this.effectdirection==2) //Bottom
					this.SetY(f_page_h-this.height-(f_page_h-this.effectend_y-this.height)*r);
				if(this.effectdirection==3) //Left
					this.SetX(this.effectend_x*r);
				break;
			}
			
			setTimeout("q_OnEffectTimer("+this.index+")", 100);
		}
	}
}

//--- Visibility Methods

function q_bc_Show(s)
{
	this.showing = s;
	
	//Make sure it's created, the 1st time we show it
	if(!this.created && s) this.Create();
	
	//Update visiblity
	if(this.created)
    	q_SetVisible("i_"+this.index+"_d", s & this.visible);
}

function q_bc_SetVisible(v)
{
	this.visible = v;
	
	if(this.created && this.showing)
    	q_SetVisible("i_"+this.index+"_d", v & this.showing);

	this.changed |= 128;
}

function q_bc_GetVisible()
{
	return this.visible;
}

function q_bc_SetTag(t)
{
	this.tag = t;
	this.changed |= 256;
}

function q_bc_GetTag()
{
	return this.tag;
}

function q_bc_SetEnabled(e)
{
	this.enabled = e;
	this.changed |= 16;
}

function q_bc_GetEnabled()
{
	return this.enabled;
}

function q_bc_SetReadOnly(r)
{
	this.readonly = r;
	this.changed |= 32;
}

function q_bc_GetReadOnly()
{
	return this.readonly;
}

function q_bc_SetShaded(s) //TO DO Created
{
	this.shaded = s;

    if(this.created)
    	this.SetHTMLMainDivBackCol(this.GetShadedColor(this.backcol));

	this.changed |= 64;
}

function q_bc_GetShaded()
{
	return this.shaded;
}

//Helper
function q_bc_GetShadedColor(c)
{
    if(this.shaded)
        return "ff0000";
    else
        return c;
}

function q_bc_SetTransparency(t) //0-100% //TO DO Created
{
	this.transparency = t;

    if(this.created)
	    q_SetTransparency("i_"+this.index+"_d", t); //0 to 100

	//Log
	this.changed |= 512;
}

//Shortcut function for scripting to set Visible/Enabled/ReadOnly
function q_bc_SetMode(v)
{
    if(v&256)
    {
        //New Style: Visibility (0=Unchaged, 1=Visible, 2=Hidden)
        var s = (v>>4)&15;
        if(s>0)
            this.SetVisible(s==1);
        
        //New Style: State (0=Unchanged, 1=Editable, 2=Flashing, 3=Shaded, 4=ReadOnly, 5=Disabled)
        s = v&15;
        if(s>0)
        {
            this.SetShaded(s==3);
            this.SetReadOnly(s==4);
	        this.SetEnabled(s!=5);
	        if(s==2) this.StartFlashing(6);
        }
    }
    else
    {
        //Old style
        this.SetVisible((v&1)>0);        
    	this.SetReadOnly((v&2)>0);
	    this.SetEnabled((v&4)>0);
	    this.SetShaded((v&8)>0);
	    if(v&16) this.StartFlashing(6);
    }
}


//--- Data Handling Methods

function q_bc_CheckObligatory()
{
	return true; //true=Everything is fine
}

function q_bc_GetData()
{
	return null;
}

function q_bc_SetData(fieldname, value)
{
	return false;
}

function q_bc_CopyData(id)
{
	//Works only with single-fields, all others must be overwritten

	//Get Source controls
	var c = q_GetControlByID(id);
	
	//Must exists and also be of same type
	if(c!=null && c.type==this.type)
		this.SetData(this.id, c.GetValue());
}

function q_bc_ResetProperties()
{
	this.SetVisible(true);
	this.SetEnabled(true);
	this.SetReadOnly(f_readonly);
	this.SetShaded(false);
	this.changed = 0;
}

//-- Scripting Methods

function q_bc_TriggerEvent(i, params)
{
    if(this.events!=0 && this.events[i]!="")
    	q_RunScript(this.events[i], params, this.id + "__" + i);
}

function q_bc_GetScriptingValue()
{
	//This is baseclass works for single-field objects only
	//Multiple fields object must override this
	var d = this.GetData();
	if(d!=null)
	{
		var s = d[0].indexOf("|");
		if(s>0) return q_HandleNumeric(d[0].substring(s+1));
	}
	
	//Else, no data or error
	return null;
}

function q_bc_SetScriptingValue(v)
{
    //Only works with single-fields, all others must overwrite
	this.SetData(this.id, v);
}


function q_bc_DoNothing()
{
	return null;
}


//--- HTML Form Helpers (to access the HTML form in ojbect's MainDiv)

function q_bc_GetHTMLForm()
{
	return document.forms["f_i_"+this.index+"_d"];
}

function q_bc_GetHTMLElement(e)
{
	return this.GetHTMLForm().elements[e];
}
	
function q_bc_GetHTMLElementValue(e)
{
	return this.GetHTMLForm().elements[e].value;
}

function q_bc_SetHTMLElementValue(e, v)
{
	this.GetHTMLForm().elements[e].value = v;
}

function q_bc_GetHTMLElementSelectedIndex(e)
{
	return this.GetHTMLForm().elements[e].options.selectedIndex;
}

function q_bc_SetHTMLElementSelectedIndex(e, i)
{
	this.GetHTMLForm().elements[e].options.selectedIndex = i;
}

function q_bc_GetHTMLElementSelectedValue(e)
{
	var i = this.GetHTMLForm().elements[e].options.selectedIndex;
	if(i<0)
		return null;
	else
		return this.GetHTMLForm().elements[e].options[i].value;
}

function q_bc_SetHTMLElementSelectedValue(e, v)
{
    var o = this.GetHTMLForm().elements[e].options;    

    if(v==null)
    {
        //Deselect all
    	o.selectedIndex = -1;
    }
    else
    {
        for(var i=0; i<o.length; i++)
        {
            if(o[i].value==v)
            {
                o[i].selected = true;
                return;
            }
        }
    }
}

function q_bc_GetHTMLElementOptions(e)
{
	return this.GetHTMLForm().elements[e].options;
}

function q_bc_SetHTMLMainDivBackCol(c)
{
	q_SetBackCol("i_"+this.index+"_d", c);
}

function q_bc_SetHTMLElementBackCol(e, c)
{
	q_SetElementBackCol(this.GetHTMLForm().elements[e],  c);
}

function q_bc_GetHTMLImage(e)
{
 	return q_GetImage("i_"+this.index+"_d", e);
}	

function q_bc_GetHTMLElementCaretPos(e)
{
	return q_GetCaretPos(this.GetHTMLElement(e));
}

function q_bc_SetHTMLElementCaretPos(e, p)
{
	q_SetCaretPos(this.GetHTMLElement(e), p);
}


//--- Other Methods

function q_bc_GoTo(f)
{			
	q_GoToControl(this.id, f);
}
//---------------------------------------------------------
//---------------------- Text Label  ----------------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: text, alignment

function q_la(index, a)
{
	//Store baseclass properties
	var n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.text = f_strings[a[n]];	//Text to be displayed
	this.align = a[n+1];			//Alignment 1=Left, 2=Right, 3=Center + >>2 1=Top, 2=Bottom, 3=Center 
	this.events = a[n+2];			//Event triggers ([0]=Cicked, [1]=Over, [2]=Out)	
	
	//Handle Text Tokens
	this.caption = q_Replace(q_Replace(q_Replace(q_Replace(this.text, "%%", "~%~"), "%p", this.page+1), "%t", f_pages_n), "~%~", "%");
	 
	//Methods (Overwrites)
	this.Create = q_la_Create;	
	this.SetData = q_la_SetData;
	this.SetCaption = q_la_SetCaption;
	
	if(this.events!=0)
	{
	    if(this.events[0]!="") this.OnMouseDown = q_la_OnMouseDown;
	    if(this.events[1]!="") this.OnMouseOver = q_la_OnMouseOver;
	    if(this.events[2]!="") this.OnMouseOut = q_la_OnMouseOut;
    }
}


//--- HTML Writer ---

function q_la_Create()
{
	//HTML
	var c = '<span id=i_'+this.index+'_ltx style="color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '"';
	
	//Event triggers (MouseDown, MouseOver & MouseOut)
	if(this.events!=0)
	{
		c += ' onmouseover="q_OnMouseOver(event, '+this.index+');" onmouseout="q_OnMouseOut(event, '+this.index+');"' +
			 ' onclick="q_OnMouseDownEx(event, '+this.index+');"';
			 
        //Show mouse pointer, on hover?
		if(this.events[0]!="") c += ' class=st_p';
	}
	
	c += '><span>' + this.caption + '</span></span>';

	//Put it into table
	c =  '<table cellspacing=0 cellpadding=0 border=0 width=' + this.cwidth + ' height=' + this.cheight + '>'
		+	'<tr><td width=' + this.cwidth + ' height=' + this.cheight + ' ' + q_GetAlignHTML(this.align) + ' class="st_nb">' + c + '</td>'
		+	'</tr></table>';
	
    //Create it
	this.CreateMainDiv(c, false);
}


//--- Scripting API ---

function q_la_SetData(fn, v)	//Undocumented, only for Peter
{
	if(fn!=this.id) return false;
	else
	{
		this.SetCaption(v);
		return true;
	}
}

function q_la_SetCaption(t)
{
    if(this.created)
        q_SetHTML("i_"+this.index+"_ltx", t);
	
	//Log
	this.caption = t;
	this.changed |= 4096;
}


//--- Event Handling Stuff ---

function q_la_OnMouseDown()
{
	this.TriggerEvent(0); //On Click
}

function q_la_OnMouseOver()
{
	this.TriggerEvent(1); //On Mouse Over
}

function q_la_OnMouseOut()
{
	this.TriggerEvent(2); //On Mouse Out
}
//---------------------------------------------------------
//---------------------- Text Input  ----------------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: multiline, maxchars, initialtext, events

function q_tx(index, a)
{
	//Store baseclass properties
	var n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.multiline = (a[n]>0);				//Is it single line or multiline?
	this.maxchars = a[n+1];					//Maximum number of chars
	this.format = a[n+2];					//Format: 0=Normal, 1=Password, 2=Alpha, 3=AlphaNumeric, 4=Email, 5=URL, 6=Mask
	this.mask = f_strings[a[n+3]];			//Mask (if Format is 6)
	this.initialtext = f_strings[a[n+4]];	//Text to be displayed
	this.events = a[n+5];					//Event triggers ([0]=Focus, [1]=Change)
	
	//Working Properties
	this.data = this.initialtext;
	
	//Methods (Overwrites)
	this.Create = q_tx_Create;
	this.SetBackCol = q_tx_SetBackCol;
	this.SetReadOnly = q_tx_SetReadOnly;
	this.SetShaded = q_tx_SetShaded;
	this.SetEnabled = q_tx_SetEnabled;
	
	this.CheckValid = q_tx_CheckValid;
	this.CheckObligatory = q_tx_CheckObligatory;
	this.GetData = q_tx_GetData;
	this.GetDataHelper = q_tx_GetDataHelper;
	this.SetData = q_tx_SetData;
	this.ResetData = q_tx_ResetData;
		
	//Event handling methods (Overwrites)
	this.OnKeyPress = q_tx_OnKeyPress;
	this.OnKeyRelease = q_tx_OnKeyRelease;
	this.OnFocus = q_tx_OnFocus;
	this.OnChange = q_tx_OnChange;

	//Rules: "9"=0-9, "a"= A-Z, "b"=A-Z,Accents, "c"=A-Z,0-9, "d"=A-Z,0-9,Accents, "*"=Anything	
	this.maskrules = {"9":/[0-9]/, "c":/[A-Z0-9]/i, "d":/[A-Z0-9\xC1-\xFF]/i, "b":/[A-Z\xC1-\xFF]/i, "a":/[A-Z]/i, "*": /./};

	//Mask Helpers
	this.AddChar = q_tx_AddChar;
	this.ValidateMask = q_tx_ValidateMask;
}


//--- HTML Writer ---

function q_tx_Create()
{
	var h, s;

    //Style
	s = 'style="width: ' + q_GetControlWidth(this.cwidth) + 'px; height: ' + q_GetControlHeight(this.cheight) + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '"';

    //HTML
	if(this.multiline)
	{
	    //Multiline
		h = '<textarea ' + s + ' wrap="soft" tabindex=' + this.tab + ' cols=' + (this.cwidth/10) + ' rows=' + (this.cheight/22) + ' maxlength=' + this.maxchars + q_GetDisabledAttribute(this.enabled) + ' onkeypress="return q_OnKeyPress(event, '+this.index+');" onfocus="q_OnFocus(event, '+this.index+');" onchange="q_OnChange(event, '+this.index+');" onkeyup="return q_OnKeyRelease(event, '+this.index+')";>' + this.data + '</textarea>';
	}
	else	
	{
	    //Single line
		var mc = '';
		if(this.maxchars>0) mc = 'maxlength=' + this.maxchars;		

		h = '<input ' + s + ' size='+q_GetCharSize(this.font, this.cwidth)+' tabindex='+this.tab+' type="' +(this.format==1?'password':'text') + '" value="' + this.data + '" ' + mc + q_GetDisabledAttribute(this.enabled) + ' onkeypress="return q_OnKeyPress(event, '+this.index+');" onfocus="q_OnFocus(event, '+this.index+');" onchange="q_OnChange(event, '+this.index+');" onkeyup="return q_OnKeyRelease(event, '+this.index+')";>';
	}
	
	//Create it
	this.CreateMainDiv(h, true);
}


//--- Property Handling Methods ---

function q_tx_SetBackCol(c)
{
	this.backcol = c;
	
	if(this.created)
	{
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(c));
	    this.SetHTMLElementBackCol(0, this.GetShadedColor(c));
    }

    //Log
	this.changed |= 8;
}

function q_tx_SetReadOnly(r)
{
	//Remember the current value, in case the user deletes it
	if(r) this.data = this.GetDataHelper();

	//Change status
	this.readonly = r;
	
	if(this.created)
    	this.GetHTMLElement(0).readonly = r;

    //Log
	this.changed |= 32;
}

function q_tx_SetShaded(r)
{
	this.shaded = r;
	
	if(this.created)
	{
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(this.backcol));
	    this.SetHTMLElementBackCol(0, this.GetShadedColor(this.backcol));
    }
    
    //Log
	this.changed |= 64;
}

function q_tx_SetEnabled(r)
{
	this.enabled = r;

	if(this.created)
 	    this.GetHTMLElement(0).disabled = !r;

    //Log
	this.changed |= 16;
}


//--- Data Handling Methods ---

function q_tx_CheckValid()
{
	var v = this.GetDataHelper();
	if(this.format==4 && v!="" && !q_IsValidEmail(v)) return q_Texts[17];
	if(this.format==5 && v!="" && !q_IsValidURL(v)) return q_Texts[18];
	return null;
}

function q_tx_CheckObligatory()
{
	return !(this.required && this.enabled && (this.GetDataHelper() == ""));
}

function q_tx_GetData()
{
	var d = new Array(1);
	d[0] = this.id + "|" + this.GetDataHelper();
	return d;
}

function q_tx_GetDataHelper()
{
	//To avoid readonly deletes
	if(!this.created || this.readonly)
		return q_Trim(this.data);
	else
		return "" + q_Trim(this.GetHTMLElementValue(0));
}

function q_tx_SetData(fn, v)
{
	if(fn!=this.id) return false;
	else
	{
		//Validate Value
		v=""+v;
		if(this.maxchars>0 && v.length>=this.maxchars) v=v.substring(0, this.maxchars);
		
		//Set it
		this.data = v;
    	if(this.created)
		    this.SetHTMLElementValue(0, v);

		//Event trigger
		this.TriggerEvent(1); //On Change
		
		return true;
	}
}

function q_tx_ResetData()
{
	this.ResetProperties();
	
	this.data = this.initialtext;
	if(this.created)
	    this.SetHTMLElementValue(0, this.initialtext);
}


//--- Event Handlers ---

function q_tx_OnKeyPress(k, t)
{
	//If Read-Only don't allow any changes
	if(this.readonly || !this.enabled || !this.created) return false;
	
	//Backspace and cursors are always ok
	if(k!=8 && k!=0 && (k<33 || k>40))
	{
		//New character entered
		var c = String.fromCharCode(k);

		//Suppress "ENTER" key to submit
		if(!this.multiline && k==13) return false;
		
		//Suppress Non-Alpha if Format = 2
		if(this.format==2 && (k<97 || k>122) && (k<65 || k>90) && k!=32) return false;

		//Suppress Non-AlphaNumeric if Format = 3
		if(this.format==3 && (k<97 || k>122) && (k<65 || k>90) && (k<48 || k>57) && k!=32) return false;

		//Enforce maximum allowed chars
		if(this.maxchars>0 &&
			(""+this.GetHTMLElementValue(0)).length >= this.maxchars) return false;
		
		//Enforce mask
		if(this.format==6)
		{	
			//Get current entered value and length
			var v = ""+this.GetHTMLElementValue(0),
				vl = v.length,
				ml = this.mask.length,
				p, m;
			
			//Get Caret Position
			p = this.GetHTMLElementCaretPos(0);
			if(p<0 || p>vl) p=vl; //If not valid, assume it's at the end

			//Cannot add at end if full
			if(vl>=ml && p>=vl) return false;

			//Check character with mask
			m = this.mask.charAt(p);
			if(this.maskrules[m.toLowerCase()])
			{
				//It's must be a special character: Test it
				if(this.maskrules[m.toLowerCase()].test(c))
				{
					//It's ok, add or overwrite, and move to next caret pos
					v = this.AddChar(v, c, p++, ml);
				}
				else
				{
					//It's not ok, abandon
					return false;
				}
			}
			else
			{
				//It's a fixed literal. Is it the one that's typed?
				if(c==m)
				{
					//Yes, correct literal is typed, add or overwrite, and move to next caret pos
					v = this.AddChar(v, c, p++, ml);
				}
				else
				{		
					//No, incorrect literal is typed, write all literals until next mask position
					while(true)
					{
						//Add literal character
						v = this.AddChar(v, m, p++, ml);
						
						//End of mask reached?
						if(p>=ml) break;
						 
						//Otherwise, look at next character
						m = this.mask.charAt(p);
						
						//Is it a special character?
						if(this.maskrules[m.toLowerCase()])
						{
							//Yes, special character: If it matches add it, otherwise ignore
							if(this.maskrules[m.toLowerCase()].test(c))
								v = this.AddChar(v, c, p++, ml);
							
							//Stop loop
							break;
						}
						//Else: Literal: Keep adding (while-loop)
					}
				}
			}
			
			//Make sure mask is intact (and apply Uppercase masks)
			v = this.ValidateMask(v);
			
			//Update Display, and suppress key
			this.SetHTMLElementValue(0, v);
			
			//Put Caret
			if(p>v.length) p=v.length;
			this.SetHTMLElementCaretPos(0, p);
			
			//Suppress automatic insert
			return false;
		}
	}
	
	//Not handled
	return true;
}

function q_tx_OnKeyRelease(k)
{
	if(this.format==6)
	{
		//Make sure mask is intact
		var v = this.GetHTMLElementValue(0),
			w = this.ValidateMask(v),
			p;
		
		//Has it changed?
		if(w!=v)
		{
			//Remember Caret Pos
			p = this.GetHTMLElementCaretPos(0);

			//Update Text
			this.SetHTMLElementValue(0, w);
			
			//Put Caret at same pos
			if(p<w.length && p>=0) this.SetHTMLElementCaretPos(0, p);
		}
	}
	
	this.TriggerEvent(2); //On Key Change
}

function q_tx_OnFocus()
{
	this.TriggerEvent(0); //On Focus
}

function q_tx_OnChange()
{
	this.TriggerEvent(1); //On Change
}


//Mask Helpers
function q_tx_ValidateMask(v)
{
	var i=0, j=0, m, c, w="", vl = v.length, ml = this.mask.length;
	while(i<vl && j<ml)
	{
		c = v.charAt(i);
		m = this.mask.charAt(j);
		if((this.maskrules[m.toLowerCase()] && this.maskrules[m.toLowerCase()].test(c)) || (m==c))
		{
			//It's perfect match, move to next one
			
			//Handle uppercase mask
			if(m.toLowerCase()!=m)
				w += c.toUpperCase();
			else
				w += c;
				
			i++;
			j++;
		}
		else
		{
			//No match
			if(this.maskrules[m.toLowerCase()])
			{
				//It a special character, skip to next source character, maybe that one will fit
				i++;
			}
			else
			{
				//It must a literal: Use it, and move to next mask character
				w += m;
				j++;
			}
		}
	}
	
	return w;
}

function q_tx_AddChar(s, c, p, m)	//s=String, c=Char to add, p=Position wher to add, m=Max length of string
{
	var l = s.length;
	
	//Append at end?
	if(p==l && l<m) return s+c;
	
	//Add in middle
	if(p>=0 && p<l)
	{
		//Insert or overwrite?
		if(l<m)
			//Insert
			return s.substring(0,p)+c+s.substring(p,l);
		else
			//Overwrite
			return s.substring(0,p)+c+s.substring(p+1,l);			
	}
	
	//None of above, return unchanged
	return s;
}
//---------------------------------------------------------
//-------------------- Numeric Input  ---------------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: digitsbeforecoma, digitsaftercoma, initialvalue, events

function q_nu(index, a)
{
	//Store baseclass properties
	var n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.digitsbeforecoma = a[n];			//Number of digits before coma
	this.digitsaftercoma = a[n+1];			//Mumber of digits after coma
	//n+2 see below
	this.events = a[n+3];					//Event triggers ([0]=Focus, [1]=Change)
	
	//Methods (Overwrites)
	this.Create = q_nu_Create;
	this.SetBackCol = q_nu_SetBackCol;
	this.SetReadOnly = q_nu_SetReadOnly;
	this.SetEnabled = q_nu_SetEnabled;
	this.SetShaded = q_nu_SetShaded;
	
	this.CheckObligatory = q_nu_CheckObligatory;
	this.GetData = q_nu_GetData;
	this.GetDataHelper = q_nu_GetDataHelper;
	this.SetData = q_nu_SetData;
	this.ResetData = q_nu_ResetData;
	
	//Event handling methods (Overwrites)
	this.OnKeyPress = q_nu_OnKeyPress;
	this.OnKeyRelease = q_nu_OnKeyRelease;
	this.OnFocus = q_nu_OnFocus;
	this.OnBlur = q_nu_OnBlur;
	this.OnChange = q_nu_OnChange;
	
	//Helper
	this.Validate = q_nu_Validate;	//Validates while inputting

	//Make sure initial value is valid
	this.initialvalue = this.Validate(f_strings[a[n+2]], true);	//Text to be displayed
	this.data = this.initialvalue;
}


//--- HTML Writer ---

function q_nu_Create()
{
    //HTML
	var h =	'<input style="width: ' + q_GetControlWidth(this.cwidth) + 'px; height: ' + q_GetControlWidth(this.cheight) + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; text-align: right; '
			+ q_GetFontCSS(this.font) + '" size=' + q_GetCharSize(this.font, this.width) + ' tabindex=' + this.tab + ' type="text" value="' + this.data + '" maxlength='+this.maxchars + q_GetDisabledAttribute(this.enabled) + ' onkeyup="return q_OnKeyRelease(event, '+this.index+')"; onkeypress="return q_OnKeyPress(event, '+this.index+');"  onfocus="q_OnFocus(event, '+this.index+');" onblur="q_OnBlur(event, '+this.index+');" onchange="q_OnChange(event, '+this.index+');">';
			
    //Create it
	this.CreateMainDiv(h, true);
}


//--- Property Handling Methods ---

function q_nu_SetBackCol(c)
{
	this.backcol = c;
	
	if(this.created)
	{
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(c));
	    this.SetHTMLElementBackCol(0, this.GetShadedColor(c));
    }
    
    //Log
	this.changed |= 8;
}

function q_nu_SetReadOnly(r)
{
	//Remember the current value, in case the user deletes it
	if(r) this.data = this.GetDataHelper();

	this.readonly = r;

	if(this.created)
	    this.GetHTMLElement(0).readonly = r;

    //Log
	this.changed |= 32;
}

function q_nu_SetEnabled(r)
{
	this.enabled = r;

	if(this.created)
    	this.GetHTMLElement(0).disabled = !r;

    //Log
	this.changed |= 16;
}

function q_nu_SetShaded(r)
{
	this.shaded = r;
	
	if(this.created)
	{
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(this.backcol));
	    this.SetHTMLElementBackCol(0, this.GetShadedColor(this.backcol));
    }
    
    //Log
	this.changed |= 64;
}


//--- Data Handling Methods ---

function q_nu_CheckObligatory()
{
	return !(this.required && this.enabled && (this.GetDataHelper() == ""));
}

function q_nu_GetData()
{
	var v = this.GetDataHelper();
	if(v=="") return null;

	var d = new Array(1);
	d[0] = this.id + "|" + v;
	return d;
}

function q_nu_GetDataHelper()
{
	//To avoid readonly deletes
	if(!this.created || this.readonly)
		return q_Trim(this.data);
	else
		return "" + q_Replace(q_Trim(this.GetHTMLElementValue(0)), ",", ".");
}

function q_nu_SetData(fn, v)
{
	if(fn!=this.id) return false;
	else
	{
		//Round
		if(v!="")
		{
			v=parseFloat(v);
			var ex=Math.pow(10, this.digitsaftercoma);
			v = Math.round(v*ex)/ex;
		}
		
		//Validate Value 
		v = this.Validate(v, true);
		
		//Make sure it doesn't end with . or ,
		if(v.length>0)
		{
			c = v.charAt(v.length-1);
			if(c=="," || c==".") v=v.substring(0, v.length-1);
		}
	
		//Set it
		this.data = v;
		if(this.created)
    		this.SetHTMLElementValue(0, v);
		
		//Event trigger
		this.TriggerEvent(1); //On Change
		
		return true;
	}
}

function q_nu_ResetData()
{
	this.ResetProperties();
	
	this.data = this.initialvalue;
	if(this.created)
    	this.SetHTMLElementValue(0, this.initialvalue);
}


//--- Event Handlers ---

function q_nu_OnKeyPress(k, t)
{
	//If Read-Only don't allow any changes
	if(this.readonly || !this.enabled || !this.created) return false;

	//Allow Cursors or DEL or BACKSPACE
	if(k==0 || k==8) return true;
	
	//Current Value
	var v = this.GetHTMLElementValue(0); 

	//Dont allow any more chars if already full (unless it's ',' / ',' or '-'
	var c=0;
	var m=0;
	if(v.indexOf(",")>=0)c++;
	if(v.indexOf(".")>=0)c++;
	if(v.indexOf("-")>=0)m++;
	if((this.digitsbeforecoma+this.digitsaftercoma)<=(v.length-c-m) && k!=44 && k!=45 && k!=46) return false;
	if(c==0&&(this.digitsbeforecoma)<=(v.length-m) && k!=44 && k!=45 && k!=46) return false;

	//Allow 0 to 9
	if(k>=48 && k<=57) return true; 

	//Allow '-', if not already in it
	if(k==45 && v.indexOf("-")<0) return true; 

	//Allow ',' and '.', if not already in it
	if (this.digitsaftercoma>0 && ((k==44 || k==46) && v.indexOf(",")<0 && v.indexOf(".")<0)) return true; 

	
	//Everything else, disallow
	return false;
}

function q_nu_OnKeyRelease(t)
{
	var v1 = this.GetHTMLElementValue(0);	//Original Value
	var v2 = this.Validate(v1, false);
	
	//If it has been corrected, change it
	if(v2!=v1) this.SetHTMLElementValue(0, v2);
	
	this.TriggerEvent(2); //On Key Change

	return true;
}

function q_nu_OnFocus()
{
	this.TriggerEvent(0); //On Focus
}

function  q_nu_OnBlur()
{
	var v1 = this.GetHTMLElementValue(0);	//Original Value
	var v2 = this.Validate(v1, true);
	
	//If it has been corrected, change it
	if(v2!=v1) 
	{
		this.SetHTMLElementValue(0, v2);
		if(q_bFirefox2)
			this.TriggerEvent(1); //On Change
	}
}

function q_nu_OnChange()
{
	this.TriggerEvent(1); //On Change
}


//Helper
function q_nu_Validate(v1, z)	//if z=true, add 0's at end
{
	//Make sure its a string
	v1 = v1 + "";
		
	//Corrected Value
	var c, v2="", v3="";
	
	//Remove illegal chars
	var commafound=false;
	for(var i=v1.length-1; i>=0; i--)
	{
		c=v1.charAt(i);
		
		//Copy if number or "-"
		if((c>="0" && c<="9") || (i==0 && c=='-')) v2=c+v2;
		
		//Copy if point or comma (but only once)
		if((c=="." || c==",") && !commafound)
		{
			v2=c+v2;
			commafound=true;
		}
	}
	
	//Check max digits
	commafound=false;
	var digitscount=0;
	for(var i=0; i<v2.length; i++)
	{
		c=v2.charAt(i);		
		if(c=="-") v3=v3+c;	//Let "-" pass through without any special action
		else
		{
			if((c=="." || c==","))
			{
				commafound=true;
				digitscount=0;
				v3=v3+c;
			} 
			else
			{
				//Must be number
				
				if((!commafound && (digitscount<this.digitsbeforecoma))
					|| (commafound && (digitscount<this.digitsaftercoma)))
				{
					v3=v3+c;
					digitscount++;
				}
			}				
		}
	}

	//Make sure it has all digits after comma (.00)
	if(z && this.digitsaftercoma>0 && v3!="")
	{
		if(commafound)
		{
			//Add more 0's
			for(var i=0; i<this.digitsaftercoma-digitscount; i++)
				v3+="0";		
		}
		else
		{
			//Add "." and 0's
			v3+=".";
			for(var i=0; i<this.digitsaftercoma; i++)
				v3+="0";
		}
	}
	
	return v3;
}
//---------------------------------------------------------
//-------------------- Static Picture  --------------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: pic, picwidth, picheight

function q_pi(index, a)
{
	//Store baseclass properties
	var n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.pic = a[n];			//Number of emoticon pictures
	this.picwidth = a[n+1];
	this.picheight = a[n+2];
	this.events = a[n+3];		//Event triggers ([0]=Cicked, [1]=Over, [2]=Out)

	//Default Poroperties
	this.source = f_resources[this.pic].src;
 	
	//Methods (Overwrites)
	this.Create = q_pi_Create;
	if(this.events!=0)
	{
	    if(this.events[0]!="") this.OnMouseDown = q_pi_OnMouseDown;
	    if(this.events[1]!="") this.OnMouseOver = q_pi_OnMouseOver;
	    if(this.events[2]!="") this.OnMouseOut = q_pi_OnMouseOut;
    }
    	
	//Scripting Method
	this.SetSource = q_pi_SetSource;
}


//--- HTML Writer ---

function q_pi_Create()
{
	//Write Main-Div containing Pic
	var c = '<img src="' + this.source + '" width=' + this.picwidth + ' height=' + this.picheight + ' name="i_'+this.index+'_pc" galleryimg="no" ';
	if(this.events!=0 && this.events[0]!="")
	    c += 'class=st_p '; //If click event, have hand-pointer

	//Event triggers (MouseOver & MouseOut)
	if(this.events!=0 && (this.events[1]!="" || this.events[2]!=""))
		c += 'onmouseover="q_OnMouseOver(event, '+this.index+');" onmouseout="q_OnMouseOut(event, '+this.index+');" ';

    //Close tag	
	c += '>';
	
	//Create it
	this.CreateMainDiv(c, false);
}

function q_pi_OnMouseDown()
{
	this.TriggerEvent(0); //On Click
}

function q_pi_OnMouseOver()
{
	this.TriggerEvent(1); //On Mouse Over
}

function q_pi_OnMouseOut()
{
	this.TriggerEvent(2); //On Mouse Out
}

//Scripting Methods
function q_pi_SetSource(s)
{
    if(this.created)
    	this.GetImage("i_"+this.index+"_pc").src = s;

	//Log
	this.source = s;
	this.changed |= 2048;
}
//---------------------------------------------------------
//----------------------- Checkboxes  ---------------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: answertype, minanswers, maxanswers, buttonsize, buttonpic, captiononright, align, answers, events
//Answers: x, y, w, h, text, value, checked

function q_ch(index, a)
{
	//Store baseclass properties
	var n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.answertype = a[n];			//0..Single, 1..Multi, 2..User Defined
	this.minanswers = a[n+1];		//If answertype=2: Minimum answers needed
	this.maxanswers = a[n+2];		//If answertype=2: Maximum answers allowed
	this.buttonsize = a[n+3];		//Width and height of checkbox button
	this.buttonpic = a[n+4];		//Picture index of checkbox pic, must be followed by "ticked" pic
	this.captiononright = (a[n+5]>0);//Are captions on right, not left?
	this.align = a[n+6];			//Aligment of caption
	this.randomize = (a[n+7]>0);	//Randomize
	var aa = a[n+8];				//Array of answers
	this.events = a[n+9];			//Event triggers ([0]=Focus, [1]=Change)

	//Treat answers
	var an = aa.length;
	this.answers_n = an;			//Number of answers

	this.answers = new Array(an);
	for(var i=0; i<an; i++)
	{
		this.answers[i] = new Object();
		this.answers[i].x = aa[i][0];
		this.answers[i].y = aa[i][1];
		this.answers[i].width = aa[i][2];
		this.answers[i].height = aa[i][3];
		this.answers[i].caption = f_strings[aa[i][4]];
		this.answers[i].value = f_strings[aa[i][5]];
		this.answers[i].initialchecked = (aa[i][6]>0);
		this.answers[i].checked = (aa[i][6]>0);
	}
	
	//Randomization
	if(this.randomize)
	{
		//Simply shuffle x/y positions
		for(var i=0; i<an; i++)
		{
			var s0 = Math.floor(Math.random()*an);
			var s1 = Math.floor(Math.random()*an);
		
			//Swap indexes
			var ox = this.answers[s0].x;
			var oy = this.answers[s0].y;
			this.answers[s0].x = this.answers[s1].x;
			this.answers[s0].y = this.answers[s1].y;
			this.answers[s1].x = ox;
			this.answers[s1].y = oy;
		}
	}

	//Constants
	this.gap = 5;					//Width of gap between checkbox and caption

	//Working variables
	this.currentlypressedcheckbox = -1;	//Index of checkbox that has been pressed down (remember it for Mouse Up)
	this.mousedownx = - 1;
	this.mousedowny = - 1;
	this.lastselected = null;			//Scripting/Multi-answer only: Index of check box that was selected last (null if none de-selected)
	
	//Methods (Overwrites)
	this.Create = q_ch_Create;
	this.Show = q_ch_Show;
	
	//Proprerty handling methods (Overwrites)
	this.SetX = q_ch_SetX;
	this.SetY = q_ch_SetY;
	this.SetVisible = q_ch_SetVisible;
	this.SetZOrder = q_ch_SetZOrder;
	this.SetEnabled = q_ch_SetEnabled;
	this.SetTransparency = q_ch_SetTransparency;
	
	this.CheckObligatory = q_ch_CheckObligatory;
	this.GetData = q_ch_GetData;
	this.SetData = q_ch_SetData;
	this.ResetData = q_ch_ResetData;
	this.CopyData = q_ch_CopyData;
	
	//Scripting methods
	this.GetState = q_ch_GetState;
	this.SetState = q_ch_SetState;
	this.SetValue = q_ch_SetValue;
	this.GetValue = q_ch_GetValue;
	this.GetValueCaption = q_ch_GetValueCaption;

	//Event handling methods (Overwrites)
	this.OnMouseDown = q_ch_OnMouseDown;
	this.OnMouseMove = q_ch_OnMouseMove;
	this.OnMouseUp = q_ch_OnMouseUp;
}


//--- HTML Writer ---

function q_ch_Create()
{
	//Create empty main div
	this.CreateMainDiv("&nbsp;", false);
	
	//Write Div for each answer
	for(var i=0; i<this.answers_n; i++)
	{
		var h =	'<table cellspacing=0 cellpadding=0 border=0 width='+this.answers[i].width+' height='+this.answers[i].height+'><tr>';
		
		var checktd, captd, gaptd;
		checktd = '<td width='+this.buttonsize+' '+q_GetAlignHTML(this.align)+'><img src="'+f_resources[parseInt(this.buttonpic)+parseInt((this.answers[i].checked?1:0)+(this.enabled?0:2))].src+'" width='+this.buttonsize+' height='+this.buttonsize+' name="i_'+this.index+'_ich'+i+'" class="st_p"></td>';
		gaptd =	'<td width='+this.gap+'><img src="'+f_resources[0].src+'" width='+this.gap+' height=2></td>'; 
		captd = '<td width='+(this.answers[i].width-this.buttonsize-this.gap)+' style="color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '" '+q_GetAlignHTML(this.align)+'>'+this.answers[i].caption+'</td>';

		if(this.captiononright) h += checktd + gaptd + captd;
		else h += captd + gaptd + checktd;
				
		h += '</tr></table>';

        this.CreateDiv('i_'+this.index+'_ch'+i,
                        this.x + this.answers[i].x,
                        this.y + this.answers[i].y,
                        this.zorder*10+11,
                        h, false, false, this.answers[i].width);
	}
}


//--- Event Handlers ---

function q_ch_OnMouseDown(eX, eY, id)
{
	//Don't do anything if disabled or read-only
	if(this.readonly || !this.enabled) return true;

	//Register Focus and to OnFocus Event
	q_RegisterFocus(this.index);
	this.TriggerEvent(0); //On Focus
	
	//Check if clicked on checkbox pic
	if(id.indexOf("i_"+this.index+"_ich")==0)
	{
		//Get index of answer clicked
		var i = parseInt(id.substring(("i_"+this.index+"_ich").length));

		if(i>=0 && i<this.answers_n)
		{
			//Remember stuff for Mouse Up
			this.currentlypressedcheckbox = i;
			this.mousedownx = eX;
			this.mousedowny = eY;
			
			//Draw temporary gray button
			q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
				f_resources[this.buttonpic+parseInt(this.answers[this.currentlypressedcheckbox].checked?1:0)+2].src;
						
			//Capture Mouse
			q_CaptureMouse(this.index);
			return false;
		}				
	}
	
	return true;
}

function q_ch_OnMouseMove(eX, eY)
{
	var pic = parseInt(this.answers[this.currentlypressedcheckbox].checked?1:0);
	
	//Move away?
	if(Math.abs(eX-this.mousedownx)<this.buttonsize && Math.abs(eY-this.mousedowny)<this.buttonsize)
	{
		//No, draw temporary gray button
		pic += 2;
	}
	//else, draw normal image
	
	//Update picture
	q_GetImage("i_"+this.index+"_ch"+this.currentlypressedcheckbox, "i_"+this.index+"_ich"+this.currentlypressedcheckbox).src =
		f_resources[this.buttonpic+pic].src;
		
	return false;
}

function q_ch_OnMouseUp(eX, eY)
{
	var i = this.currentlypressedcheckbox;
	
	//Only if mouse hasn't move away too far
	if(Math.abs(eX-this.mousedownx)<this.buttonsize && Math.abs(eY-this.mousedowny)<this.buttonsize)
	{
		//Checkbox was clicked!	
		if(this.answertype==0)
		{
			//Single Answer
			this.answers[i].checked = !this.answers[i].checked;

			//If this is check uncheck all others
			if(this.answers[i].checked)
			{
				//Uncheck all others
				for(var j=0; j<this.answers_n; j++)
					if(j!=i && this.answers[j].checked)
					{
						//Uncheck it
						this.answers[j].checked = false;
						
						//Change Image
						q_GetImage("i_"+this.index+"_ch"+j, "i_"+this.index+"_ich"+j).src =
							f_resources[parseInt(this.buttonpic)].src;
					}
			}
		}
		else
		{
			//Multiple Answers
			
			if(this.answertype==2)
			{
				//User Defined (Min, Max)
				var count=0;
				for(var j=0; j<this.answers_n; j++) if(this.answers[j].checked) count++;

				//Is Max Answers already reached?
				if(this.answers[i].checked || count<this.maxanswers)
				{
					this.answers[i].checked = !this.answers[i].checked;
				}
			}
			else
			{
				//Simply change status of clicked checkbox
				this.answers[i].checked = !this.answers[i].checked;
			}
				
			//Remember this one as last checked
			if(this.answers[i].checked)
			{
				this.lastselected = i;
				this.changed |= 16384;
			}
		}
		
		//Event Trigger
		this.TriggerEvent(1); //On Change
	}
		
	//Change Image
	q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
		f_resources[parseInt(this.buttonpic)+parseInt(this.answers[i].checked?1:0)].src;
		
	//Release Mouse
	q_ReleaseMouse(this.index);
}


//--- Visibility Methods ---

function q_ch_Show(s)
{
	this.showing = s;

	//Make sure it's created, the 1st time we show it
	if(!this.created && s) this.Create();
	
	//Update visiblity
	if(this.created)
	{
	    q_SetVisible("i_"+this.index+"_d", s & this.visible);
    	
	    for(var i=0; i<this.answers_n; i++)
		    q_SetVisible("i_"+this.index+"_ch"+i, s & this.visible);
    }
}

function q_ch_SetVisible(v)
{
	this.visible = v;
	
	if(this.created && this.showing)
    {
        //Background main div
	    q_SetVisible("i_"+this.index+"_d", v & this.showing);
	
	    //Each answer div
	    for(var i=0; i<this.answers_n; i++)
		    q_SetVisible("i_"+this.index+"_ch"+i, v & this.showing);
    }
    
	this.changed |= 128;
}

function q_ch_SetTransparency(t) //TO DO in HTML!
{
	this.transparency = t;

	if(this.created)
	{
	    q_SetTransparency("i_"+this.index+"_d", t);
    	
	    for(var i=0; i<this.answers_n; i++)
		    q_SetTransparency("i_"+this.index+"_ch"+i, t);
	}

	//Log
	this.changed |= 512;
}


//--- Data Handling Methods ---

function q_ch_CheckObligatory() //TO DO
{
	//How many checked
	var count=0;
	for(var j=0; j<this.answers_n; j++) if(this.answers[j].checked) count++;

	//Nothing checked and obligatory? Or User-defined and Min answers not reached?
	return !(this.enabled && ((count==0 && this.required) || (this.answertype==2 && count<this.minanswers)));
}

function q_ch_GetData()
{
	if(this.answertype==0)
	{
		//Single Answer
		var d = new Array(1);
		for(var i=0; i<this.answers_n; i++)
			if(this.answers[i].checked)
			{
				d[0] = this.id + "|" + this.answers[i].value;
				return d;
			}
				
		//Nothing checked
		d[0] = this.id + "|"; //Return empty value
		return d;
	}
	else
	{
		//Multiple Answers
		var answersfound = 0;
		var d = new Array();
		for(var i=0; i<this.answers_n; i++)
			if(this.answers[i].checked || this.answers[i].initialchecked)
				d[answersfound++] = this.id + "_" + (i+1) + "|" + parseInt(this.answers[i].checked?1:0);
				
		if(answersfound>0) return d;
		//Nothing checked
		else return null;
	}
}

function q_ch_SetData(fn, v)
{
	if(this.answertype==0)
	{
		//Single Answer
		if(fn!=this.id) return false;
		else
		{
			for(var i=0; i<this.answers_n; i++)
			{
				this.answers[i].checked = (v==this.answers[i].value);
				
				//Update Image
				if(this.created)
				    q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
					    f_resources[parseInt(this.buttonpic)+parseInt(this.answers[i].checked?1:0)].src;
			}
			
			//Event trigger
			this.TriggerEvent(1); //On Change
			
			return true;
		}
	}
	else
	{
		//Multiple Answers
		for(var i=0; i<this.answers_n; i++)
		{
			if((this.id+"_"+(i+1))==fn)
			{
				this.answers[i].checked = (v=="1");
				
				//Update Image
				if(this.created)
				    q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
					    f_resources[parseInt(this.buttonpic)+parseInt(this.answers[i].checked?1:0)].src;

				//Remember last checked
				if(this.answers[i].checked && !f_preloading)
				{
					this.lastselected = i;
					this.changed |= 16384;
				}
				
				//Event trigger
				this.TriggerEvent(1); //On Change
				
				return true;
			}
		}
		return false;
	}
}

function q_ch_ResetData()
{
	this.ResetProperties();

	for(var i=0; i<this.answers_n; i++)
	{
		this.answers[i].checked = this.answers[i].initialchecked;
		
		//Update Image
    	if(this.created)
	    	q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
		    	f_resources[parseInt(this.buttonpic)+parseInt(this.answers[i].checked?1:0)].src;
	}
	this.lastselected = null;
}

function q_ch_CopyData(id)
{
	//Find object from ID
	var c = q_GetControlByID(id);
	
	//Must exists and also be a table
	if(c!=null && c.type==this.type)
	{
		//Clear all
		for(var i=0; i<this.answers_n; i++)
			this.answers[i].checked = false;
			
		//Find all checked ones in source
		for(var i=0; i<c.answers_n; i++)
			if(c.answers[i].checked)
			{
				//Found, now look for matching value
				for(var j=0; j<this.answers_n; j++)
					if(c.answers[i].value==this.answers[j].value)
					{
						//Match found. Check it
						this.answers[j].checked  = true;
						break;
					}
			}
			
		//Update images
    	if(this.created)
    		for(var i=0; i<this.answers_n; i++)
	    		q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
		    		f_resources[parseInt(this.buttonpic)+parseInt(this.answers[i].checked?1:0)].src;
	}
}


//--- Scripting Methods ---

function q_ch_GetState(i)
{
	//Validate
	if(i<1 || i>this.answers_n) return null;

	return this.answers[i-1].checked;
}

function q_ch_SetState(i, b)
{
	//Validate
	if(i<1 || i>this.answers_n) return;
	
	//Do it
	i--;
	
	if(this.answertype==0 && b)
	{
		//Single Answer Checked
		for(var j=0; j<this.answers_n; j++)
		{
			this.answers[j].checked = (i==j);
			
			//Update image
    	    if(this.created)
			    q_GetImage("i_"+this.index+"_ch"+j, "i_"+this.index+"_ich"+j).src =
				    f_resources[parseInt(this.buttonpic)+parseInt(this.answers[j].checked?1:0)].src;
		}		
	}
	else
	{
		//Multi Answer checked/unchecked, or Single Answer unchecked

		this.answers[i].checked = b;

		//Update image
	    if(this.created)
    		q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
	    		f_resources[parseInt(this.buttonpic)+parseInt(this.answers[i].checked?1:0)].src;
			
		//Remember last checked
		if(b)
		{
			this.lastselected = i;		
			this.changed |= 16384;
		}
	}
	
	//Event trigger
	this.TriggerEvent(1); //On Change
}

function q_ch_SetValue(v)
{
	if(this.answertype==0)
	{
		//Single Response
		return this.SetData(this.id, v);
	}
	else
	{
		//Multiresponse
		if(v==null || v=="")
		{
			//Clear all
			for(var i=0; i<this.answers_n; i++)
			{
				this.answers[i].checked = false;
				
				//Update Image
        	    if(this.created)
	    			q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
		   				f_resources[parseInt(this.buttonpic)].src;
			}
			
			//Event trigger
			this.TriggerEvent(1); //On Change
		}
		else
		{
			//Select one
			for(var i=0; i<this.answers_n; i++)
			{
				if(this.answers[i].value == v)
				{
					this.answers[i].checked = true;
					
				    //Update Image
        	        if(this.created)
					    q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
						    f_resources[parseInt(this.buttonpic)+1].src;
						
					this.lastselected = i;
					this.changed |= 16384;
					
					//Event trigger
					this.TriggerEvent(1); //On Change
				}
			}
		}
	}
}

function q_ch_GetValue()
{
	if(this.answertype==0)
	{
		//Single Response
		for(var i=0; i<this.answers_n; i++)
			if(this.answers[i].checked)
				return q_HandleNumeric(this.answers[i].value);
		
		//Else
		return null;
	}
	else
	{
		//Multiresponse
		
		//Anything checked at all (in case last answer got unchecked)?
		for(var i=0; i<this.answers_n; i++)
		{
			if(this.answers[i].checked)
			{
				//Yes, at least one answer is still checked
				if(this.lastselected!=null && this.answers[this.lastselected].checked)
					return q_HandleNumeric(this.answers[this.lastselected].value);
				else
					return q_HandleNumeric(this.answers[i].value);
			}
		}
		//No, nothing checked
		return null;		
	}
}

function q_ch_GetValueCaption()
{
	if(this.answertype==0)
	{
		//Single Response
		for(var i=0; i<this.answers_n; i++)
			if(this.answers[i].checked) return this.answers[i].caption;
			
		//Nothing checked
		return null;
	}
	else
	{
		//Anything checked at all (in case last answer got unchecked)?
		for(var i=0; i<this.answers_n; i++)
		{
			if(this.answers[i].checked)
			{
				//Yes, at least one answer is still checked
				if(this.lastselected!=null && this.answers[this.lastselected].checked)
					return this.answers[this.lastselected].caption;
				else
					return this.answers[i].caption;
			}
		}
		//No, nothing checked
		return null;
	}
}


//--- X/Y Postion Methods ---

function q_ch_SetX(x)
{
	if(x>=0 && x<=f_page_w-this.width)
	{
		this.x = x;
		
		if(this.created)
    	{
		    q_SetLeft("i_"+this.index+"_d", x);
		
		    for(var i=0; i<this.answers_n; i++)
			    q_SetLeft("i_"+this.index+"_ch"+i, x + this.answers[i].x);
        }
        
		this.changed |= 1;
	}
}

function q_ch_SetY(y)
{
	if(y>=0 && y<=f_page_h-this.height)
	{
		this.y = y;
		
		if(this.created)
    	{
		    q_SetTop("i_"+this.index+"_d", y);
		
		    for(var i=0; i<this.answers_n; i++)
			    q_SetTop("i_"+this.index+"_ch"+i, y + this.answers[i].y);
        }
        
		this.changed |= 2;
	}
}

function q_ch_SetZOrder(z)
{
	if(z>=0 && z<3276)
	{
		this.zorder = z;
		
		if(this.created)
    	{
		    q_SetZOrder("i_"+this.index+"_d", z*10+10);
    		
		    for(var i=0; i<this.answers_n; i++)
			    q_SetZOrder("i_"+this.index+"_ch"+i, z*10+11);
        }
        
		this.changed |= 4;
	}
}

function q_ch_SetEnabled(e)
{
	this.enabled = e;
	
	if(this.created)
   	{
	    //Gray out images
	    var g = e?0:2;
	    for(var i=0; i<this.answers_n; i++)
	    {
		    q_GetImage("i_"+this.index+"_ch"+i, "i_"+this.index+"_ich"+i).src =
			    f_resources[parseInt(this.buttonpic)+parseInt(this.answers[i].checked?1:0)+g].src;
	    }
    }
    
	this.changed |= 16;
}
//---------------------------------------------------------
//------------------ Drop-Down Selection  -----------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: answers[], values[], selected, events

function q_dd(index, a)
{
	//Store baseclass properties
	n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.answers = a[n];			//Array that contains all the answer labels
	this.values = a[n+1];			//Array that contains all the answer values
	this.initialselected = a[n+2];	//Initially selected answer (-1 if none)
	this.randomize = (a[n+3]>0);	//Randomize
	this.events = a[n+4];			//Event triggers ([0]=Focus, [1]=Change)
	
	//Defaults
	this.data = this.initialselected;	//Used for read-only functionality, etc...
	this.changedanswers = null;		    //Stores string if SetAnswers ist used (for state info)

	//Order / Randomization / Get String Values
	this.order = new Array();
	for(var i=0; i<this.answers.length; i++)
	{
		this.order[i] = i;
		this.answers[i] = f_strings[this.answers[i]];
		this.values[i] = f_strings[this.values[i]];
	}
	if(this.randomize) q_Randomize(this.order, 0, this.answers.length);

	//Methods (Overwrites)
	this.Create = q_dd_Create;
	this.SetBackCol = q_dd_SetBackCol;
	this.SetReadOnly = q_dd_SetReadOnly;
	this.SetEnabled = q_dd_SetEnabled;
	this.SetShaded = q_dd_SetShaded;
	
	this.GetData = q_dd_GetData;
	this.GetDataHelper = q_dd_GetDataHelper;
	this.SetData = q_dd_SetData;
	this.ResetData = q_dd_ResetData;
	this.CopyData = q_dd_CopyData;
	this.CheckObligatory = q_dd_CheckObligatory;
	
	//Scripting methods
	this.GetValueCaption = q_dd_GetValueCaption;
	this.GetState = q_dd_GetState;
	this.SetState = q_dd_SetState;
	this.SetAnswers = q_dd_SetAnswers;

	//Event handling	
	this.OnChange = q_dd_OnChange;
	this.OnFocus = q_dd_OnFocus;
}


//--- HTML Writer ---

function q_dd_Create()
{
	var h = '<select tabindex=' + this.tab + ' width=' + q_GetControlWidth(this.width) + ' size=1 style="width: ' + q_GetControlWidth(this.cwidth) + 'px; height: ' + q_GetComboBoxHeight(this.cheight) + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '"' + q_GetDisabledAttribute(this.enabled) + ' onchange="return q_OnChange(event, ' + this.index + ');" onfocus="q_OnFocus(event, ' + this.index + ');">';
	
	//Nothing selected by default?
	if(this.initialselected<0)
	{
		h += '<option value="-1"';
		if(this.data<0) h += ' selected';
		h += '>&nbsp;</option>';
	}
	
	//Add each answer as <option/>
	for(var i=0; i<this.answers.length; i++)
	{
		h += '<option value="'+this.order[i]+'"';
		if(this.order[i]==this.data) h += ' selected';
		h += '>'+this.answers[this.order[i]]+'</option>';
	}
	
	h += '</select>';
	
	//Create it
	this.CreateMainDiv(h, true);
}


//--- Property Handling Methods ---

function q_dd_SetBackCol(c)
{
	this.backcol = c;

	if(this.created)
  	{
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(c));
	    this.SetHTMLElementBackCol(0, this.GetShadedColor(c));
    }

    //Log    
	this.changed |= 8;
}

function q_dd_SetReadOnly(r)
{
    //Remember ReadOnly value
   	this.data = this.GetDataHelper();

	this.readonly = r;
	
    //Log    
	this.changed |= 32;
}

function q_dd_SetEnabled(r)
{
	this.enabled = r;
	
	if(this.created)
    	this.GetHTMLElement(0).disabled = !r;
	
	//Log
	this.changed |= 16;
}

function q_dd_SetShaded(r)
{
	this.shaded = r;

	if(this.created)
	{	
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(this.backcol));
	    this.SetHTMLElementBackCol(0, this.GetShadedColor(this.backcol));
    }

    //Log    
	this.changed |= 64;
}


//--- Data Handling Methods ---

function q_dd_CheckObligatory()
{
	return !(this.required && this.enabled && this.GetDataHelper()<0);
}

function q_dd_GetData()
{
	//Is "nothing" selected?
	if(this.GetDataHelper()<0)
	{
	    //Nothing selected
	    return null;
	}
	else
	{
	    //Something is selected
	    var d = new Array(1);
	    d[0] = this.id + "|" + this.values[this.GetDataHelper()];
	    return d;
	}
}

function q_dd_GetDataHelper()
{
	if(!this.created || this.readonly)
		return this.data;
	else
		return this.GetHTMLElementSelectedValue(0);
}

function q_dd_SetData(fn, v)
{
	if(fn!=this.id) return false;
	else
	{
		for(var i=0; i<this.answers.length; i++)
		{
		    //Find matching value
			if(v==this.values[i])
			{
				//Store it
				this.data = i;

                //Display it
                if(this.created)            
    				this.SetHTMLElementSelectedValue(0,	i);
								
				//Event trigger
				this.TriggerEvent(1); //On Change
				
				return true;
			}
		}
		return false;
	}
}

function q_dd_ResetData()
{
	this.ResetProperties();

	this.data = this.initialselected;
	
	if(this.created)
    	this.SetHTMLElementSelectedValue(0, this.data);
}

function q_dd_CopyData(id)
{
	//Find object from ID
	var c = q_GetControlByID(id);
	
	//Must exists and also be a drop-down
	if(c!=null && c.type==this.type)
	{
		//Select empty by default
		if(this.initialselected<0)
		    this.data = -1;

        //Select same value (look for it, if it exists)
		var v = c.GetValue();
	    for(var i=0; i<this.answers.length; i++)
	        if(v==this.values[i])
	        {
	            //Matching value found
	            this.data = i;
	            break;
	        }

        //Update display
    	if(this.created)
        	this.SetHTMLElementSelectedValue(0,	this.data);
	}
}


//---- Scripting methods ---

function q_dd_GetValueCaption()
{
	//Disabled or "nothing" selected?
	if(!this.enabled || this.GetDataHelper()<0) return null;

	//Return Caption
	return this.answers[this.GetDataHelper()];
}

function q_dd_GetState(i)
{
	//Validate
	if(i<1 || i>this.values.length) return null;

	return (parseInt(this.GetDataHelper()) == i-1);
}

function q_dd_SetState(i, b)
{
	//Validate
	if(i<1 || i>this.values.length) return;
	
    //Set/Unset
	if(b)
    	this.data = i-1;
	else
    	this.data = this.initialselected;
	
	if(this.created)
    	this.SetHTMLElementSelectedValue(0,	this.data);
	
	//Event trigger
	this.TriggerEvent(1); //On Change
}

function q_dd_SetAnswers(aa)
{
	//Validate
	var a = (aa+"").split("|");
	var n = a.length;
	if(n<2 || (n&1)==1) return; //Illegal argument
	n/=2;
	
	//Update Properties
	this.answers = new Array();			//Array that contains all the answer labels
	this.values = new Array();			//Array that contains all the answer values
	this.order = new Array();
	for(var i=0; i<n; i++)
	{
		this.answers[i] = a[i*2]; 
		this.values[i] = a[i*2+1];
		this.order[i] = i;
	}
	this.initialselected = -1;          //Nothing selected initially

	//Randomization
	if(this.randomize) q_Randomize(this.order, 0, n);
	
	//Update Control
	if(this.created)
	{
	    var c = this.GetHTMLElement(0);
	    c.length = 0;
	    c.options[0] = new Option(" ", "-1"); //Empty 1st one
	    for(var i=0; i<n; i++) c.options[i+1] = new Option(this.answers[this.order[i]], this.order[i]);
    }
    
	//Log
	this.changedanswers = aa;
	this.changed |= 1024;
}


//---- Event handling methods ---

function q_dd_OnChange()
{
	if(this.readonly || !this.enabled)
	{
		//Restore previous value
		this.SetHTMLElementSelectedValue(0, this.data);
	}
	else
	{
		//Event Trigger
		this.TriggerEvent(1); //On Change
	}
}

function q_dd_OnFocus()
{
	this.TriggerEvent(0); //On Focus
}
//---------------------------------------------------------
//----------------------- Date/Time -----------------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: date(not time), initialvalue, format, labels, firstyear, lastyear, calendar, etc..

function q_dt(index, a)
{
	//Store baseclass properties
	var n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.input = a[n];						//1..Time / 2...Date / 3..Both
	this.dateformat = a[n+1];				//1..Month Follows Day / 2..Include Years
	this.timeformat = a[n+2];				//1..24 hours clock / 2...Include Seconds
	this.dateinput = a[n+3];				//1..Pop-up Calendar / 2..Month names not numbers
	this.initialvalue = a[n+4];             //Initial value (YYYYMMDD HH:mm:SS), "n"=Now, ""=Empty
	this.firstyear = parseInt(a[n+5]);		//First item in Year combo
	this.lastyear = parseInt(a[n+6]);		//Last itme in Year combo
	this.calendar_pics = a[n+7];			//Picture Index to Pics used in Pop-up Calendar (0..Pop-up Button, 2..Minus Button, 4..Plus Button, 6...Close Button)
	this.calendar_font = a[n+8];			//font used in Calendar
	this.calendar_cols = a[n+9];			//Colors[] used in Calendar 0..Background, 1..Text, 2..Header Backgr, 3..Header Text, 4..Highlight Backgr, 5..Highlight Text
	this.events = a[n+10];					//Event triggers ([0]=Focus, [1]=Change)
			
	//Culture Constants
	this.date_separator = "-";
	this.month_longnames = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");
	this.month_shortnames = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
	this.week_abr = "wk";
	this.weekdays_shortnames = new Array("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
	this.first_weekday = 0;
	
	//Pop-up Calendar Variables
	this.calendar_showing = false;
	this.day_offset = 0;						//Position of Day "1" in Grid (0-6)

	//Width and height of Calendar table based on font size
	var fh =parseInt((f_fonts[this.calendar_font].split("|"))[0]);
	this.calendar_cellwidth = parseInt(fh * 5 / 2) + 2;	
	this.calendar_cellheight = fh + 8;	
	this.calendar_buttonsize = fh + 1;
	this.calendar_textboxwidth = this.cheight*4;			
	
	//Position of Calendar (relative to Object pos)
	//Top or bottom?
	if(this.y>this.calendar_cellheight*9								//Enough room on the top
			&& this.y+this.cheight+this.calendar_cellheight*9>f_page_h)	//Not much space on the bottom
		this.calendar_y = 0-this.calendar_cellheight*9-1;				//On top
	else
		this.calendar_y = this.cheight+1;								//On bottom
	//Left or right?
	if(this.x>this.calendar_cellwidth*8-this.cwidth						//Enough room on the left
			&& this.x+this.calendar_cellwidth*8>f_page_w)				//Not much space on the right
		this.calendar_x = this.cwidth-this.calendar_cellwidth*8-3;		//On left
	else
		this.calendar_x = 0;											//On right
		
	this.mousedownx = - 1;
	this.mousedowny = - 1;
	this.currentlypressedbutton = -1;
	this.currentlypressedbutton_name = null;
	this.currentlypressedbutton_pic = 0;
	
	//Methods (Overwrites)
	this.Create = q_dt_Create;
	this.Show = q_dt_Show;
	this.SetVisible = q_dt_SetVisible;
	this.SetBackCol = q_dt_SetBackCol;
	this.SetReadOnly = q_dt_SetReadOnly;
	this.SetEnabled = q_dt_SetEnabled;
	this.SetShaded = q_dt_SetShaded;

	this.CheckValid = q_dt_CheckValid;
	this.CheckObligatory = q_dt_CheckObligatory;
	this.GetData = q_dt_GetData;
	this.GetDataHelper = q_dt_GetDataHelper;
	this.SetData = q_dt_SetData;
	this.ResetData = q_dt_ResetData;
	this.CopyData = q_dt_CopyData;
	
	this.GetValue = q_dt_GetValue;
	this.GetValueCaption = q_dt_GetValueCaption;
	this.SetValue = q_dt_SetValue;

	this.OnKeyPress = q_dt_OnKeyPress;
	this.OnChange = q_dt_OnChange;
	this.OnFocus = q_dt_OnFocus;
	this.OnFocusLost = q_dt_OnFocusLost;
	this.OnMouseOver = q_dt_OnMouseOver;
	this.OnMouseOut = q_dt_OnMouseOut;
	this.OnMouseDown = q_dt_OnMouseDown;
	this.OnMouseMove = q_dt_OnMouseMove;
	this.OnMouseUp = q_dt_OnMouseUp;
	
	//Pop-Up Calender Helpers
	this.CalendarShow = q_dt_CalendarShow;
	this.CalendarPopulate = q_dt_CalendarPopulate;
	
	//Helpers
	this.UpdateDisplay = q_dt_UpdateDisplay;
	this.ApplyBackColor = q_dt_ApplyBackColor;
	this.GetComboHTML = q_dt_GetComboHTML;
	this.ParseDateTimeString = q_dt_ParseDateTimeString;
	this.ParseDateTimeDataString = q_dt_ParseDateTimeDataString;
    this.FormatDateString = q_dt_FormatDateString;
    this.FormatTimeString = q_dt_FormatTimeString;
	this.MatchMonth = q_dt_MatchMonth;
	this.IsValidDate = q_dt_IsValidDate;
	this.GetNumberOfDaysInMonth = q_dt_GetNumberOfDaysInMonth;
	this.GetWeekNumber = q_dt_GetWeekNumber;
	
	//Set Initial Data
	this.data = this.ParseDateTimeDataString(this.initialvalue);
}


//--- HTML Writer ---

function q_dt_Create()
{
	//Space-savers
	var i = this.index,
	
	   //Re-usable <td>
	   td = '<td style="height: ' + this.cheight + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '; background-image: none">',
	   
	   //Is nothing selected?
       em = (this.data.getTime()==0),
        
	    //Output String
	    c = "";


	//Date
	if(this.input&2)
	{
		if(this.dateinput&1)
		{
			//Pop-up Calendar
			
			//Text Input
			c += td + '<input size='+q_GetCharSize(this.font, this.calendar_textboxwidth)+' id=i_'+i+'_tx tabindex='+this.tab+' value="'+this.FormatDateString(this.data)+'" style="width: ' + q_GetControlWidth(this.calendar_textboxwidth) + 'px; height: ' + q_GetControlHeight(this.cheight) + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '"' + q_GetDisabledAttribute(this.enabled) + ' onfocus="q_OnFocus(event, '+i+');" onkeypress="return q_OnKeyPress(event, '+i+');" onchange="q_OnChange(event, '+i+');"></td>';

			//Gap (2 Pixels)
			c += td + '<img src="'+f_resources[0].src+'" width=2 height='+this.cheight+'></td>';
					
			//Button (Width = (h-2)*5/6; Height = h-2)
			c += td + '<img src="'+f_resources[this.calendar_pics].src+'" width='+parseInt((this.cheight-2)*5/6)+' height='+(this.cheight-2)+' name="i_'+i+'_bu" galleryimg=no class=st_p></td>';
		}
		else
		{
			//Combobox Menus
			
			//Day
			var d = this.GetComboHTML("da", 1, 31, this.data.getDate(), false, em);
			
			//Month
			var m;
			if(this.dateinput&2)
			{
				//Use names
				var m =	td + '<select tabindex=' + this.tab + ' size=1 id=i_'+i+'_mo style="height: ' + q_GetComboBoxHeight(this.cheight) + 'px; width: ' + (this.cheight*5/2) + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '"' + q_GetDisabledAttribute(this.enabled) + ' onchange="return q_OnChange(event, '+i+');" onfocus="q_OnFocus(event, '+i+');">';
				
				if(this.initialvalue=="") m += '<option value="-1" selected>&nbsp;</option>'; 

				for(var j=1; j<=12; j++)
				{
					m += '<option value="'+j+'"';
					if(!em && j==(this.data.getMonth()+1)) m += ' selected ';
					m += '>'+this.month_shortnames[j-1]+'</option>';
				}
				
				m += "</select>";
			}
			else
			{
				//Use numbers
				m = this.GetComboHTML("mo", 1, 12, this.data.getMonth()+1, false, em);
			}
			
			//Day and Month order
			if(this.dateformat&1)
				c += d+m;
			else
				c += m+d;

			//Year
			if(this.dateformat&2)
				c += this.GetComboHTML("ye", this.firstyear, this.lastyear, this.data.getFullYear(), false, em);	
		}
	}


	//Gap
	if((this.input&3)==3)
		c += td + '<img src="' + f_resources[0].src + '" width='+this.cheight+' height='+this.cheight+'></td>';


	//-- Time --
	
	if(this.input&1)
	{		

		//Hours: Handle 24(0-23)/12(1-12) clock
		var ih = this.data.getHours();
		if(!(this.timeformat&1)) 
		{
			//12 hour clock: Initial value (0=>12)
			ih = ih%12;
			if(ih==0) ih=12;
		}
		c += this.GetComboHTML("ho", (this.timeformat&1)?0:1, (this.timeformat&1)?23:12, ih, true, em);
		
		//Minutes
		c += this.GetComboHTML("mi", 0, 59, this.data.getMinutes(), true, em);		


		//Seconds (if included)
		if(this.timeformat&2)
			c += this.GetComboHTML("se", 0, 59, this.data.getSeconds(), true, em);
	
		//AM/PM
		if(!(this.timeformat&1)) 
		{
			c += td + '<select tabindex='+this.tab+' size=1 id=i_'+i+'_am style="height: ' + this.cheight + 'px; background-color: #' + this.GetShadedColor(this.backcol) +  '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '"' + q_GetDisabledAttribute(this.enabled) + ' onchange="return q_OnChange(event, '+i+');" onfocus="q_OnFocus(event, '+i+');">';
	
			//Empty initial value
			if(this.initialvalue=="") c += '<option value="-1" selected>&nbsp;</option>';

			//am
			c += '<option value=0';
			if(!em && this.data.getHours()<12) c += " selected ";
			c += '>am</option>';

			//pm
			c += '<option value=1';
			if(!em && this.data.getHours()>=12) c += ' selected ';
			c += '>pm</option>';
			
			c += '</select>';
		}
	}
		
    //Put it all in a table
	c  = '<table cellspacing=0 cellpadding=0 border=0><tr>' + c + '</tr></table>';

	//Create it
	this.CreateMainDiv(c, true);
		

		
	//--- Write Pop-up Calendar Divs ---

	if(this.input&2 && this.dateinput&1)
	{
		//Space saving (cell size)
		var s = 'width: ' + this.calendar_cellwidth + '; height: ' + this.calendar_cellheight + ';';

		c = '<table cellspacing=0 cellpadding=0 border=0 style="background-color: #' + this.calendar_cols[0] + '; ' + q_GetFontCSS(this.calendar_font) + '; text-align: center; border: 1px solid #' + this.calendar_cols[1] + '">';
			
		//Year Header
		var cl = 'style="height:' + this.calendar_cellheight + '; border-bottom: 1px solid #' + this.calendar_cols[1] + '; background-color: #' + this.calendar_cols[2] + '; color: #' + this.calendar_cols[3] + '"';
		var bs = "width=" + this.calendar_buttonsize + " height=" + this.calendar_buttonsize + " class=st_p name=i_"+i+"_";
		c += '<tr><td '+cl+'>&nbsp;</td>'
				+	'<td '+cl+'><img src="'+f_resources[this.calendar_pics+2].src+'" '+bs+'bym></td>'		//Year minus button
				+	"<td colspan=4 "+cl+" id=i_"+i+"_cye><b>x</b></td>"
				+	'<td '+cl+'><img src="'+f_resources[this.calendar_pics+4].src+'" '+bs+'byp></td>'		//Year plus button
				+	'<td '+cl+'><img src="'+f_resources[this.calendar_pics+6].src+'" '+bs+'bcl></td></tr>';	//Close button

		//Month Header
		cl = 'style="height:' + this.calendar_cellheight + '; border-bottom: 1px solid #' + this.calendar_cols[1] + '; background-color: #' + this.calendar_cols[0] + '; color: #' + this.calendar_cols[1] + '"';
		c += '<tr><td '+cl+'>&nbsp;</td>'
				+	'<td '+cl+'><img src="'+f_resources[this.calendar_pics+2].src+'" '+bs+'bmm></td>'		//Month minus button
				+	'<td colspan=4 '+cl+' id=i_'+i+'_cmo><b>x</b></td>'
				+	'<td '+cl+'><img src="'+f_resources[this.calendar_pics+4].src+'" '+bs+'bmp></td>'		//Month plus button
				+	'<td '+cl+'>&nbsp;</td></tr>';
			
		
		//Week-Number Header
		c += '<tr><td style="' + s + ' border-bottom: 1px solid #' + this.calendar_cols[1] + '; border-right: 1px solid #' + this.calendar_cols[1] + '; background-color: #' + this.calendar_cols[2] + '; color: #' + this.calendar_cols[3] + '">' + this.week_abr + '</td>';

		//Weekdays Headers
		var j, k;
		for(j=0; j<7; j++)
			c += '<td id=i_'+i+'_cwd'+j+ ' style="' + s + ' border-bottom: 1px solid #' + this.calendar_cols[1] + '; background-color: #' + this.calendar_cols[2] + '; color: #' + this.calendar_cols[3] + '">' + this.weekdays_shortnames[(j+this.first_weekday)%7] + '</td>';
		 
		//Dates 
		for(j=0; j<6; j++) //Show 6 weeks
		{
			//Week number
			c += '<tr><td id=i_'+i+'_cwk'+j+' style="' + s + ' border-right: 1px solid #' + this.calendar_cols[1] + '; background-color: #' + this.calendar_cols[2] + '; color: #' + this.calendar_cols[3] + '">' + j + '</td>';
			
			//Week dates
			for(k=0; k<7; k++)
				c += '<td id=i_'+i+'_cda' + (j*7+k) + ' style="' + s + ' color: ' + this.calendar_cols[1] + '" class=st_p onmouseover="q_OnMouseOver(event, '+this.index+');" onmouseout="q_OnMouseOut(event, '+this.index+');">' + (j*7+k) + '</td>';

			c += '</tr>';
		}
		
		//Close Table and include IE bugfix trick
		c +=	'</table>';
		if(q_bIE) c += '<!--[if lte IE 6.5]><iframe style="position:absolute; top:0; left:0; z-index:-1; filter:alpha(opacity:0); width: ' + (this.calendar_cellwidth*8+7) + 'px; height: ' + (this.calendar_cellheight*9+2)+ 'px;"></iframe><![endif]-->';
		
		//Create it
		this.CreateDiv('i_'+i+'_ca',
		                this.x + this.calendar_x,
		                this.y + this.calendar_y,
		                29999,
		                c,
		                this.calendar_cols[0]);
	}
}


//--- Property Handling Methods ---

function q_dt_Show(s)
{
	this.showing = s;
	
	//Make sure it's created, the 1st time we show it
	if(!this.created && s) this.Create();
	
	//Update visiblity
	if(this.created)
	{
	    q_SetVisible("i_"+this.index+"_d", s & this.visible);
	
	    //Hide Pop-Up Calendar
	    if(!s && this.calendar_showing) this.CalendarShow(false);
	 }
}

function q_dt_SetVisible(v)
{
	this.visible = v;
	
	if(this.created && this.showing)
	{
	    q_SetVisible("i_"+this.index+"_d", v & this.showing);

	    //Hide Pop-Up Calendar
	    if(!v && this.calendar_showing) this.CalendarShow(false);
    }
    
    //Log
	this.changed |= 128;
}

function q_dt_SetBackCol(c)
{
	this.backcol = c;
	
	if(this.created)	
	    this.ApplyBackColor(this.GetShadedColor(c));

    //Log
	this.changed |= 8;
}


function q_dt_SetReadOnly(r)
{
	//Remember values
	this.GetDataHelper();

	this.readonly = r;
	
    //Log
	this.changed |= 32;
}

function q_dt_SetEnabled(e)
{
	this.enabled = e;

    if(this.created)
    {
	    var i = "i_"+this.index;

	    //Time
	    if(this.input&1)
	    {
		    this.GetHTMLElement(i+"_ho").disabled = !e;
		    this.GetHTMLElement(i+"_mi").disabled = !e;
		    if(this.timeformat&2) this.GetHTMLElement(i+"_se").disabled = !e;
		    if(!(this.timeformat&1)) this.GetHTMLElement(i+"_am").disabled = !e;
	    }
    	
	    //Date
	    if(this.input&2)
	    {
		    if(this.dateinput&1)
		    {	
			    //Calendar Pop-Up
			    this.GetHTMLElement(i+"_tx").disabled = !e;
		    }
		    else
		    {	
			    //Combobox Menus		
			    this.GetHTMLElement(i+"_da").disabled = !e;
			    this.GetHTMLElement(i+"_mo").disabled = !e;
			    if(this.dateformat&2) this.GetHTMLElement(i+"_ye").disabled = !e;
		    }
	    }

        //Remember ReadOnly
    	this.GetDataHelper();
	}

	this.changed |= 16;
}


function q_dt_SetShaded(r)
{
	this.shaded = r;
	
	if(this.created)
	    this.ApplyBackColor(this.GetShadedColor(this.backcol));
    
    //Log
	this.changed |= 64;
}


//Helpers
function q_dt_ApplyBackColor(c)
{
	var i = "i_"+this.index;

	//Main Div
	this.SetHTMLMainDivBackCol(c);

	//Time
	if(this.input&1)
	{
		this.SetHTMLElementBackCol(i+"_ho", c);
		this.SetHTMLElementBackCol(i+"_mi", c);
		if(this.timeformat&2) this.SetHTMLElementBackCol(i+"_se", c);
		if(!(this.timeformat&1)) this.SetHTMLElementBackCol(i+"_am", c);
	}

	//Date
	if(this.input&2)
	{
		if(this.dateinput&1)
		{	
			//Calendar Pop-Up
			this.SetHTMLElementBackCol(i+"_tx", c);
		}
		else
		{	
			//Combobox Menus		
			this.SetHTMLElementBackCol(i+"_da", c);
			this.SetHTMLElementBackCol(i+"_mo", c);
			if(this.dateformat&2) this.SetHTMLElementBackCol(i+"_ye", c);
		}
	}
}


//--- Data Handling Methods ---

function q_dt_CheckValid()
{
	return null;
}

function q_dt_CheckObligatory()
{
	this.GetDataHelper();
	return !(this.required && this.enabled && (this.data.getTime()==0));
}

function q_dt_GetData()
{
	var v = "";
	
	//Get current data in JavaScript object
	this.GetDataHelper();
	
	//Empty?
    if(this.data.getTime()==0) return null;

	//Date
	if(this.input&2)
		v += "" + q_ForceDigits(this.data.getFullYear(), 4) + q_ForceDigits(this.data.getMonth()+1, 2) + q_ForceDigits(this.data.getDate(), 2);

	//Space
	if((this.input&3)==3)
	    v += " ";
	
	//Time
	if(this.input&1)
		v += "" + q_ForceDigits(this.data.getHours(), 2) + ":" + q_ForceDigits(this.data.getMinutes(), 2) + ":" + q_ForceDigits(this.data.getSeconds(), 2);

    //Return
	var d = new Array(1);
	d[0] = this.id + "|" + v;
	return d;
}

//Returns Date() object with currently selected Date/Time
function q_dt_GetDataHelper()
{
    if(this.created && !this.readonly)
    {
        //Value from controls
        
	    var da, mo, ye, ho, mi, se,
	        i = "i_"+this.index;
    	    
	    //Set Date part
	    if(this.input&2)
	    {
		    if(!(this.dateinput&1))
		    {	
			    //Combobox Menus		
    		    ye = (this.dateformat&2)?(1*this.GetHTMLElementSelectedValue(i+"_ye")):0;
    		    mo = 1*this.GetHTMLElementSelectedValue(i+"_mo");
    		    da = 1*this.GetHTMLElementSelectedValue(i+"_da");
    		    
		        //Left empty?
		        if(ye<0 || mo<0 || da<0)
    		        this.data = new Date(0);
	    		else
    		        this.data.setFullYear(ye, mo-1, da);
		    }
    		
        }
        
	    //Set Time part
	    if(this.input&1)
	    {
		    ho = 1*this.GetHTMLElementSelectedValue(i+"_ho");
		    mi = 1*this.GetHTMLElementSelectedValue(i+"_mi");
		    se = (this.timeformat&2)?(1*this.GetHTMLElementSelectedValue(i+"_se")):0;

		    //Handle AM/PM
		    if(!(this.timeformat&1))
		    {
			    if(ho==12) ho=0;
			    if(this.GetHTMLElementSelectedValue(i+"_am")>0) ho += 12;
		    }

            //Left empty?
		    if(ho<0 || mi<0 || se<0) {ho=0; mi=0; se=0};

		    this.data.setHours(ho);
		    this.data.setMinutes(mi);
		    this.data.setSeconds(se);
	    }
    }
}

function q_dt_SetData(fn, v)
{
	if(fn!=this.id) return false;
	else
	{
	    //Set data
	    this.data = this.ParseDateTimeDataString(v);
	    
	    //Update controls
	    this.UpdateDisplay();
	    
		//Event trigger
		this.TriggerEvent(1); //On Change

		return true;
	}
}

function q_dt_ResetData()
{
	this.ResetProperties();

    //Reset to initial data
    this.data = this.ParseDateTimeDataString(this.initialvalue);
    
    //Update controls
    this.UpdateDisplay();
}

function q_dt_CopyData(id)
{
	var i = "i_"+this.index;

	//Find object from ID
	var c = q_GetControlByID(id);
	
	//Must exists and also be a table
	if(c!=null && c.type==this.type && c.GetValue()!=null)
	{
		//Get Data from Source
		this.data = new Date(c.GetValue());
		this.UpdateDisplay();
	}
}


//--- Scripting Methods ---

//Returns JavaScript Date object
function q_dt_GetValue()
{
    this.GetDataHelper();
    if(this.data.getTime()==0) return null;
	return this.data;
}

//Returns String of Date
function q_dt_GetValueCaption()
{
    //Get current date
    this.GetDataHelper();
    v = "";
        
    //Not empty
    if(this.data.getTime()!=0)
    {
	    //Date
	    if(this.input&2)
            v += this.FormatDateString(this.data);

	    //Space
	    if((this.input&3)==3)
	        v += " ";
    	
	    //Time
	    if(this.input&1)
          v += this.FormatTimeString(this.data);
    }
        
    return v;
}

//Accepts JavaScript Date object or String
function q_dt_SetValue(d)
{
	//If not Date object, try to parse string to date object
	if(!d.getFullYear)
	{
		//If successful use it as new object
		var v = this.ParseDateTimeString(""+d);
		if(v!=null) d=v;
	}

	//Is it a Date() object? Use it
	if(d.getFullYear)
	    this.data = d;
	    
    //Is it empty?
    if((d==null || d=="") && this.initialvalue=="")
	    this.data = new Date(0);
	    
	//Update Controls
	this.UpdateDisplay();
	
	//Event Trigger
	this.TriggerEvent(1); //On Change
}


//--- Event Handling Methods ---

function q_dt_OnKeyPress(k, t)
{
	//If Read-Only don't allow any changes
	if(this.readonly || !this.enabled) return false;
	
	//OK
	return true;
}


function q_dt_OnChange(t)
{
	//Handle ReadOnly
	if(this.readonly || !this.enabled)
	{
		//Restore previous values
        this.UpdateDisplay();
	}
	else
	{
		//Handle Manual Date Input
		if(t.id.indexOf("_tx")>0)
		{
			//It's the text input, parse it
			var d = this.ParseDateTimeString(this.GetHTMLElementValue(t.id));
			if(d!=null)
			{
				//Use it
				this.data.setDate(d.getDate());
				this.data.setMonth(d.getMonth());
				this.data.setFullYear(d.getFullYear());	
			}
			
			//Update Textbox (either we new one, or with previous one)
			this.SetHTMLElementValue(t.id, this.FormatDateString(this.data));
			
			//If not valid don't run Event Trigger below
			if(d==null) return;
		}

		//Event Trigger
		this.TriggerEvent(1); //On Change
	}	
}

function q_dt_OnFocus()
{
	this.TriggerEvent(0); //On Focus
}

function q_dt_OnFocusLost()
{
	//Hide Pop-Up Calendar
	if(this.calendar_showing) this.CalendarShow(false);
}


//--- Event Handler: Buttom Mouse Action ---

function q_dt_OnMouseOver(x, y, t)
{
	//Is it a date field?
	var i = "i_"+this.index+"_cda";
	if(t.id.indexOf(i)==0)
	{
		//Get index
		var n = parseInt(t.id.substring(i.length));

		//Only highlight cells with numbers		
		if(n>=this.day_offset && n<this.day_offset+this.GetNumberOfDaysInMonth(this.data.getMonth()+1, this.data.getFullYear()))
		{
			//Highlight cell
			q_SetBackCol(i+n, this.calendar_cols[4]);
			q_SetColor(i+n, this.calendar_cols[5]);
		}
	}
}

function q_dt_OnMouseOut(x, y, t)
{
	//Is it a date field?
	var i = "i_"+this.index+"_cda";
	if(t.id.indexOf(i)==0)
	{
		//Get index
		var n = parseInt(t.id.substring(i.length));
		
		//Undo Highlight cell, unless it's the current selected date
		if(n != (this.day_offset + this.data.getDate() - 1))
		{
			q_SetBackCol(i+n, this.calendar_cols[0]);
			q_SetColor(i+n, this.calendar_cols[1]);
		}
	}
}

function q_dt_OnMouseDown(eX, eY, id)
{
	//Don't do anything if disabled or read-only
	if(this.readonly || !this.enabled) return true;

	//Register Focus and to OnFocus Event
	q_RegisterFocus(this.index);
	this.TriggerEvent(0); //On Focus	

	//Remember for Mouse Up	
	this.mousedownx = eX;
	this.mousedowny = eY;

	//Space saver
	var i = "i_"+this.index;
	
	//Clicked on date cell?
	var d = i+"_cda";
	if(id.indexOf(d)==0)
	{
		//Get clicked index
		var n = parseInt(id.substring(d.length));
		
		//Only highlight cells with numbers		
		if(n>=this.day_offset && n<this.day_offset+this.GetNumberOfDaysInMonth(this.data.getMonth()+1, this.data.getFullYear()))
		{
			//Undo currently selected cell
			var u = this.day_offset + this.data.getDate() - 1;
			q_SetBackCol(d+u, this.calendar_cols[0]);
			q_SetColor(d+u, this.calendar_cols[1]);
			
			//Officially change selection
			this.data.setDate(n-this.day_offset+1);
			this.calendar_changed = true;
		
			//Highlight new selected cell
			//q_SetBackCol(d+n, this.calendar_cols[4]);
			//q_SetColor(d+n, this.calendar_cols[5]);
			
			//Close window down
			this.CalendarShow(false);
		}
	}
	
	
	//Buttons Definiations
	var bn = Array("bu", "bym", "byp", "bmm", "bmp", "bcl");	//Button names
	var bp = Array(	0,	  2,	 4,		2,	   4,	  6);		//Button pics	  
	
	//Check if clicked on any button pic?
	for(var j=0; j<bn.length; j++)
	{
		//Is it one of our buttons?
		if(id.indexOf(i+"_"+bn[j])==0)
		{
			//Yes.
			
			//Remember stuff for Mouse Up
			this.currentlypressedbutton = j;
			this.currentlypressedbutton_name = bn[j];
			this.currentlypressedbutton_pic = bp[j];
					
			//Draw "Down" button
			q_GetImage(i+"_d", i+"_"+bn[j]).src = f_resources[this.calendar_pics+bp[j]+1].src;
								
			//Capture Mouse
			q_CaptureMouse(this.index);
			return false;
		}
	}

	return true;
}

function q_dt_OnMouseMove(eX, eY)
{
	//Space saver
	var i = "i_"+this.index;
	
	//Moved by
	var d = Math.sqrt(Math.pow(Math.abs(eX-this.mousedownx),2) + Math.pow(Math.abs(eY-this.mousedowny),2));
	
	//Update picture (moved away?)
	q_GetImage(i+"_d", i+"_"+this.currentlypressedbutton_name).src = 
			f_resources[this.calendar_pics+this.currentlypressedbutton_pic+((d<this.calendar_buttonsize)?1:0)].src;
		
	return false;
}


function q_dt_OnMouseUp(eX, eY)
{
	//Space saver
	var i = "i_"+this.index;

	//Moved by
	var m = Math.sqrt(Math.pow(Math.abs(eX-this.mousedownx),2) + Math.pow(Math.abs(eY-this.mousedowny),2));

	//Depending on which button is pressed
	switch(this.currentlypressedbutton)
	{
		case 0:	//"Pop-Up" Button

			//Only if mouse hasn't move away too far
			if(m<this.cheight)
				//Clicked! Toggle Calendar
				this.CalendarShow(!this.calendar_showing);
			break;
			
		case 1:	//Year Minus
							
			if(this.data.getFullYear()>this.firstyear)
			{
				this.data.setFullYear(this.data.getFullYear()-1);
				this.calendar_changed = true;
				this.CalendarPopulate();	
			}				
			break;
			
		case 2:	//Year Plus
							
			if(this.data.getFullYear()<this.lastyear)
			{
				this.data.setFullYear(this.data.getFullYear()+1);
				this.calendar_changed = true;
				this.CalendarPopulate();	
			}				
			break;

		case 3:	//Month Minus
							
			this.data.setMonth(this.data.getMonth()-1);
			this.calendar_changed = true;
			this.CalendarPopulate();
			break;

		case 4:	//Month Plus
							
			this.data.setMonth(this.data.getMonth()+1);
			this.calendar_changed = true;
			this.CalendarPopulate();				
			break;

		case 5:	//Close
							
			this.CalendarShow(false);
			break;
	}

	//Change Button Image back to normal
	q_GetImage(i+"_d", i+"_"+this.currentlypressedbutton_name).src = 
			f_resources[this.calendar_pics+this.currentlypressedbutton_pic].src;
	
	//Release Mouse
	q_ReleaseMouse(this.index);
}


//--- Pop-Up Calendar ---

function q_dt_CalendarShow(b)
{
	//When Showing
	if(b)
	{
		//Clear Flag
		this.calendar_changed = false;
		
		//Make sure we have a date to begin with (not empty)
		if(this.data.getTime()==0)
		    this.data = new Date();

		//Make sure it's within the year range
		if(this.data.getFullYear()<this.firstyear) this.data.setFullYear(this.firstyear);
		if(this.data.getFullYear()>this.lastyear) this.data.setFullYear(this.lastyear);

		//Populate Calendar with right days
		this.CalendarPopulate();
	}
	
	//Show/Hide It
	q_SetVisible("i_"+this.index+"_ca", b);
	this.calendar_showing = b;

	//When Hiding	
	if(!b && this.calendar_changed)
	{
		//Update Textbox
		this.SetHTMLElementValue("i_"+this.index+"_tx", this.FormatDateString(this.data));

		//OnChange Trigger
		this.TriggerEvent(1); //On Change
	}
}


function q_dt_CalendarPopulate()
{
	//Write Year
	q_SetHTML("i_"+this.index+"_cye", "<b>" + this.data.getFullYear() + "</b>");
	
	//Write Month
	q_SetHTML("i_"+this.index+"_cmo", "<b>" + this.month_longnames[this.data.getMonth()] + "</b>");

	//Find out which weekday first day of the month is
	var dt = new Date(this.data.getFullYear(), this.data.getMonth(), 1);
	var w = (6+dt.getDay())%7;
		
	//Find out in which place of the calendar this weekday is
	this.day_offset = (7-this.first_weekday+w)%7;
	
	//Find out number of days in this month
	var md = this.GetNumberOfDaysInMonth(this.data.getMonth()+1, this.data.getFullYear());
	
	//Move through each field in table
	for(var j=0; j<6*7; j++)
	{
		if(j>=this.day_offset && j<this.day_offset+md)
			q_SetHTML("i_"+this.index+"_cda"+j, (j-this.day_offset+1)); 	//Write Day
		else
			q_SetHTML("i_"+this.index+"_cda"+j, ""); 						//Empty field
			
		//Highlight the right one
		var hl = (j==(this.day_offset+this.data.getDate()-1));
		q_SetBackCol("i_"+this.index+"_cda"+j, this.calendar_cols[hl?4:0]);
		q_SetColor("i_"+this.index+"_cda"+j, this.calendar_cols[hl?5:1]);
		
	}	
	
	//Write Week Numbers
	for(var j=0; j<6; j++)
		q_SetHTML("i_"+this.index+"_cwk"+j, this.GetWeekNumber(1+j*7, this.data.getMonth()+1, this.data.getFullYear()));
}



//--- Helpers ---

function q_dt_UpdateDisplay()
{
    if(this.created)
    {
		var i = "i_"+this.index;


		//--- Time ---

		if(this.input&1)
		{
		    if(this.data.getTime()==0 && this.initialvalue=="")
		    {
		        //Set it all to empty
			    this.SetHTMLElementSelectedValue(i+"_ho", -1);
			    this.SetHTMLElementSelectedValue(i+"_mi", -1);
			    if(!(this.timeformat&1)) this.SetHTMLElementSelectedValue(i+"_am", -1);
			    if(this.timeformat&2) this.SetHTMLElementSelectedValue(i+"_se", -1);
		    }
		    else
		    {
			    //Set Hour Combox
			    var ih;
			    if(this.timeformat&1) 
			    {
				    //24 hour clock
				    this.SetHTMLElementSelectedValue(i+"_ho", this.data.getHours());
			    }
			    else
			    {
				    //12 hour clock: Initial value (0=>12)
				    var ih = (this.data.getHours())%12;
				    if(ih==0) ih=12;
				    this.SetHTMLElementSelectedValue(i+"_ho", ih);
				    this.SetHTMLElementSelectedValue(i+"_am", (this.data.getHours()>=12)?1:0);
			    }
    					
			    //Set Minutes Combobox
			    this.SetHTMLElementSelectedValue(i+"_mi", this.data.getMinutes());

			    //Set Seconds Combobox
			    if(this.timeformat&2) this.SetHTMLElementSelectedValue(i+"_se", this.data.getSeconds());
		    }
		}


		//--- Date ---
		
		if(this.input&2)
		{
			if(this.dateinput&1)
			{	
				//Calendar Pop-Up
				this.SetHTMLElementValue(i+"_tx", this.FormatDateString(this.data));
			}
			else
			{	
			    //Combobox Menus		
		        if(this.data.getTime()==0 && this.initialvalue=="")
		        {
				    //All to empty
				    this.SetHTMLElementSelectedValue(i+"_da", -1);
				    this.SetHTMLElementSelectedValue(i+"_mo", -1);
				    if(this.dateformat&2) this.SetHTMLElementSelectedValue(i+"_ye",  -1);
		        }
		        else
		        {
				    this.SetHTMLElementSelectedValue(i+"_da", this.data.getDate());
				    this.SetHTMLElementSelectedValue(i+"_mo", this.data.getMonth()+1);
				    if(this.dateformat&2) this.SetHTMLElementSelectedValue(i+"_ye",  this.data.getFullYear());
				}
			}
		}		
    }
}

function q_dt_GetComboHTML(id, a, b, s, d, n)  //From a to b, s = preselected by default, d = use double digits ("02"), n = Select nothing
{
	var h =	'<td style="height: ' + this.cheight + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '; background-image: none">'+
				'<select tabindex=' + this.tab + ' size=1 id=i_'+this.index+'_'+id+' style="height: ' + q_GetComboBoxHeight(this.cheight) + 'px; width: ' + ((a>100)?(this.cheight*5/2):(this.cheight*2)) + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' +q_GetFontCSS(this.font) + '"' + q_GetDisabledAttribute(this.enabled) + ' onchange="return q_OnChange(event, '+this.index+');" onfocus="q_OnFocus(event, '+this.index+');">';
		
	//Empty option?
	if(this.initialvalue=="") h += '<option value="-1" selected>&nbsp;</option>'; 

	for(var i=a; i<=b; i++)
	{
		var v = i;
		if(d && v<10) v ="0"+v;
		
		h += '<option value="'+v+'"';
		if(!n && i==s) h += ' selected="selected"';
		h += '>'+v+'</option>';
	}
	
	return h + '</select>';
}

//Parse human entered string to Date()
function q_dt_ParseDateTimeString(s)
{	
	var valid_time = false;
	var valid_date = false;
	var d = new Date(0);


	//--- Handle Time ---

	if(false)
	{
		//TO DO
		valid_time = true;
		d.setHours(ho);
		d.setMinutes(mi);
		d.setSeconds(se);
	}

	
	//--- Handle Date ---
	
	//Split it
	var a = s.split(/[-,.\\\/\s]+/);	//Any of this characters can be used as separators

	var valid = false, da, mo, ye=0;
	
	if(a.length>1)
	{
		//At least two fields entered (Day & Month)
		var m;
		var a0 = parseInt(a[0]);
		var a1 = parseInt(a[1]);

		
		m = this.MatchMonth(a[0]);
		if(m>0 && a1>0 && a1<32)
		{
			//Valid month-name/day found
			valid = true;
			da = a1;
			mo = m;
		}
		
		m = this.MatchMonth(a[1]);
		if(m>0 && a0>0 && a0<32)
		{
			//Valid day/month-name found
			valid = true;
			da = a0;
			mo = m;
		}
		
		if(a0>0 && a0<13 && a1>12 && a1<32)
		{
			//Valid month/day found
			valid = true;
			da = a1;
			mo = a0;
		}
		
		if(a1>0 && a1<13 && a0>12 && a0<32)
		{
			//Valid month/day found
			valid = true;
			da = a0;
			mo = a1;
		}
		
		if(a0>0 && a0<13 && a1>0 && a1<13)
		{
			//Valid month/day or month/day found
			valid = true;
			if(this.dateformat&1)
			{
				da = a0;
				mo = a1;
			}
			else
			{
				da = a1;
				mo = a0;
			}
		}
		
		//Year
		if(a.length>2 && parseInt(a[2])>0)
		{
			//Year entered
			ye = parseInt(a[2]);
			if(ye<500) ye+=1900;
		}
		else
		{	
			//No (valid) year entered, keep existing one or go to current year
			if(this.data.getFullYear()>0)
				ye = this.data.getFullYear();
			else
				ye = 2000; 
				
		}
		
		//Validate year range
		if(ye<this.firstyear) ye=this.firstyear;
		if(ye>this.lastyear) ye=this.lastyear;				
	}
	
	
	//OK, do we have a valid date?
	if(valid && this.IsValidDate(da, mo, ye))
	{
		//Use it
		valid_date = true;
		d.setFullYear(ye, mo-1, da);
	}


	//--- Recognized? ---
	
	if(valid_time || valid_date) return d;
	else return null;
}

//Parses "YYYYMMDD HH:mm:SS" to Date()
function q_dt_ParseDateTimeDataString(s)
{
    //Special case "n" = Now
    if(s=="n") return new Date();
    
    //Normal case....
    var d = new Date(0),
        l = s.length,
        v;
    
    //--- Time ---
    
    //Take last 8 eight chars
	if(l>=8)
	{
		//Look for ":" in last 8 characters
		var t = s.substring(l-8,l);
		if(t.indexOf(":")>0)
		{
		    var ta = t.split(":");
		
		    //First bit is hours
		    v = ta[0]*1;
		    if(!isNaN(v) && v>=0 && v<24)
		        d.setHours(v);
		        
		    //Second bit is minutes
		    if(ta.length>1)
		    {
		        v = ta[1]*1;
    		    if(!isNaN(v) && v>=0 && v<60)
    		        d.setMinutes(v);
		    }
	
		    //Third bit is seconds
	        if(ta.length>2)
		    {
		        v = ta[2]*1;
    		    if(!isNaN(v) && v>=0 && v<60)
    		        d.setSeconds(v);
		    }
		}
    }
    
    
	//--- Date ---
	
	//Take first 8 chars	
	if(l>=8)
	{
	    //Last 2 are day
	    v = parseInt(s.substring(6,8), 10);
	    if(!isNaN(v) && v>0 && v<32)
 		    d.setDate(v); 		    
	    
	    //Middle 2 are month
	    v = parseInt(s.substring(4,6), 10);
	    if(!isNaN(v) && v>0 && v<13)
 		    d.setMonth(v-1);			
 		    
	    //First 4 are year
	    v = parseInt(s.substring(0,4), 10);
	    if(!isNaN(v))
	    {
			if(v<this.firstyear) v = this.firstyear;
			if(v>this.lastyear) v = this.lastyear;
			
 		    d.setFullYear(v);			
	    }
	}
	
	return d;
}

function q_dt_FormatDateString(d)
{
    var v = "";
    
    //Not Empty?
    if(d!=null && d.getTime()!=0)
    { 
	    //Day and Month Name
	    if(this.dateformat&1)
		    v = d.getDate() + this.date_separator + this.month_shortnames[d.getMonth()];
	    else
		    v = this.month_shortnames[d.getMonth()] + this.date_separator + d.getDate();	

	    //Year	
	    if(this.dateformat&2)
		    v += this.date_separator + d.getFullYear();
    }
        
    return v;
}

function q_dt_FormatTimeString(d)
{
    var v = "";
    
    //Not Empty?
    if(d!=null)
    { 
        //Minutes
        v += ":" + q_ForceDigits(d.getMinutes(), 2);
        
        //Seconds
        if(this.timeformat&2) 
            v += ":" + q_ForceDigits(d.getSeconds(), 2);
            
        //Hours
        var h = d.getHours();
	    if(!this.timeformat&1) 
	    {
		    //12 hour clock
		    if(h>=12)
		    {
		        //PM
		        h -= 12;
		        v += " pm";
		    }
		    else
		    {
		        //AM
		        v += " am";
		    }
		    if(h==0) h=12;
	    }
	    v = q_ForceDigits(h, 2) + v;
    }
        
    return v;
}

function q_dt_MatchMonth(s)
{
	var i;
	
	//Check for short name
	for(i=0; i<12; i++)
		if(this.month_shortnames[i].toLowerCase()==s.toLowerCase())
			return (i+1);
	
	//Check for long name
	for(i=0; i<12; i++)
		if(this.month_longnames[i].toLowerCase()==s.toLowerCase())
			return (i+1);

	//No match found
	return 0;
}

function q_dt_IsValidDate(d, m, y)
{
	return (d<=this.GetNumberOfDaysInMonth(m,y));
}

function q_dt_GetNumberOfDaysInMonth(m, y)
{
	if(m==2)
		return 28+(( (y%4==0) && ((y%100!=0)||(y%400==0)) )?1:0);
	else
		return 30+(( (m==4)||(m==6)||(m==9)||(m==11) )?0:1);
}

function q_dt_GetWeekNumber(d, m, y)
{
	//Taken from: http://www.codeproject.com/csharp/gregorianwknum.asp
    var a = Math.floor((14-(m))/12);
    y = y+4800-a;
    m = m+(12*a)-3;
    var jd = d + Math.floor(((153*m)+2)/5) + 
                 (365*y) + Math.floor(y/4) - Math.floor(y/100) + 
                 Math.floor(y/400) - 32045;    
    var d4 = (jd+31741-(jd%7))%146097%36524%1461;
    var L = Math.floor(d4/1460);
    var d1 = ((d4-L)%365)+L;
    return Math.floor(d1/7) + 1;        
}
//---------------------------------------------------------
//------------------------ Button  ------------------------
//---------------------------------------------------------


//--- Constructor ---

//Bass class: index, id, page, x, y, width, height, frame, framepic, padding, backcol, forecol, tab, zorder, required, fonts
//Ctrl specific: dispaly as pic, caption/picture index, action, param

function q_bu(index, a)
{
	//Store baseclass properties
	var n = q_bc_Constr(this, index, a);
	
	//Store control specific properties
	this.displaypic = (a[n]>0);									//true/false display as picture
	this.caption = (this.displaypic)?a[n+1]:f_strings[a[n+1]];	//Caption on button / Or picture index
	this.action = a[n+2];										//Action (0=Send, 1= )
	this.param = a[n+3];										//Additional paramater for action
	this.events = a[n+4];										//Event triggers ([0]=Focus, [1]=Change)
		
	//Methods (Overwrites)
	this.Create = q_bu_Create;
	this.SetBackCol = q_bu_SetBackCol;
	this.SetShaded = q_bu_SetShaded;
	this.SetEnabled = q_bu_SetEnabled;
	
	//Event handling methods (Overwrites)
	this.OnFocus = q_bu_OnFocus;
	if(this.displaypic)
		this.OnMouseDown = q_bu_OnChange;
	else
		this.OnChange = q_bu_OnChange;
}


//--- HTML Writer ---

function q_bu_Create()
{
	var h;
	
	//Pic or button?
	if(this.displaypic)
		h = '<img src="' + f_resources[this.caption].src + '" width=' + this.cwidth + ' height=' + this.cheight + ' name="i_' + this.index + '_pc" galleryimg=no class=st_p>';
	else
		h = '<input type="button" tabindex=' + this.tab + ' width=' + q_GetButtonWidth(this.cwidth) + ' height=' + q_GetButtonHeight(this.cheight) + ' value="' + this.caption + '"' + q_GetDisabledAttribute(this.enabled) + ' style="width: ' + q_GetButtonWidth(this.cwidth) + 'px; height: ' + q_GetButtonHeight(this.cheight) + 'px; background-color: #' + this.GetShadedColor(this.backcol) + '; color: #' + this.forecol + '; ' + q_GetFontCSS(this.font) + '" onclick="return q_OnChange(event, ' + this.index + ');" onfocus="q_OnFocus(event, ' + this.index + ');">';
	
	//Create it
	this.CreateMainDiv(h, true);
}


//--- Property Handling Methods ---

function q_bu_SetBackCol(c)
{
	this.backcol = c;

	if(this.created)
	{
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(c));
	    if(!this.displaypic) this.SetHTMLElementBackCol(0, this.GetShadedColor(c));
    }
    
    //Log
	this.changed |= 8;
}

function q_bu_SetShaded(r)
{
	this.shaded = r;
	
	if(this.created)
	{
	    this.SetHTMLMainDivBackCol(this.GetShadedColor(this.GetShadedColor(this.backcol)));
	    if(!this.displaypic) this.SetHTMLElementBackCol(0, this.GetShadedColor(this.backcol));
    }
    
    //Log
	this.changed |= 64;
}

function q_bu_SetEnabled(r)
{
	this.enabled = r;

	if(this.created && !this.displaypic)
	    this.GetHTMLElement(0).disabled = !r;

    //Log	
	this.changed |= 16;
}


//--- Event Handling Methods ---

function q_bu_OnChange(t)
{
	//Don't do anything if disabled.
	if(!this.enabled) return;
	
	//Event triggger
	this.TriggerEvent(1); //On Change

	//Do it
	switch(this.action)
	{
	case 1:
		if(!this.readonly) q_SendData();
		break;	
		
	case 2:
		if(!this.readonly) q_ResetData();
		break;	

	case 3:		q_ShowURL(this.param); break;	
	case 4:
		if(this.param=="") q_NextPage();
		else q_GoToPageName(this.param);
		break;
	case 5:		q_BackHistoryPage(); break;
	case 7:		q_Print(); break;
	case 8:		q_NextPage(); break;	
	case 9:		q_PrevPage(); break;	
	}
	return true;
}

function q_bu_OnFocus()
{
	this.TriggerEvent(0); //On Focus
}
//=========================================================
//================ WRITE OUT CSS/HTML =====================
//=========================================================


q_WriteHTML();


//=========================================================
//========================= END ===========================
//=========================================================

