var review = new Review();



/**
 * Review
 * @extends Page
 * @constructor
 */
function Review()
{
	// Call the prototype's constructor
	Page.call(this);

	// Private
	var self				= this,
		dom					= new DOM(),
		uploadsInProgress	= 0,
		uploads				= new Array();

	this.activateReviewToggle 		= activateReviewToggle;
	this.dropDownPageBox			= dropDownPageBox;
	this.ratingSelector				= ratingSelector;
	this.toggleProsCons				= toggleProsCons;
	this.toggleImages				= toggleImages;
	this.reviewImagesHandler		= reviewImagesHandler;
	this.deleteFinished 			= deleteFinished;
	this.uploadFinished 			= uploadFinished;
	this.showReviewMailer			= showReviewMailer;
	this.activateReviewVoter		= activateReviewVoter;
	this.activateCommentForm		= activateCommentForm;
	this.showCustomerImageGallery 	= showCustomerImageGallery;

	self.addEventListener(Page.LOADED, activateReviewToggle, true);
	self.addEventListener(Page.LOADED, dropDownPageBox, true);
	self.addEventListener(Page.LOADED, ratingSelector, true);
	self.addEventListener(Page.LOADED, toggleProsCons, true);
	self.addEventListener(Page.LOADED, toggleImages, true);
	self.addEventListener(Page.LOADED, reviewImagesHandler, true);
	self.addEventListener(Page.LOADED, showReviewMailer, true);
	self.addEventListener(Page.LOADED, activateReviewVoter, true);
	self.addEventListener(Page.LOADED, activateCommentForm, true)



	/**
	 * Activate the reviewscoreboard toggle
	 */
	function activateReviewToggle()
	{
		if (!dom.getById("reviews"))
		{
			return false;
		}

		var reviewLinks = dom.getById("reviews").getElementsByTagName("a");

		for (var i = 0; i < reviewLinks.length; i++)
		{
			link = dom.extend(reviewLinks[i]);
			if (link.hasClass("toggle")) 
			{
				toggle = link;
				toggle.onclick = (function(toggle)
				{
					return function(link)
					{
						var target = dom.getById(toggle.href.substr(toggle.href.indexOf("#") + 1));
						if (target) 
						{
							if (toggle.hasClass("active"))
							{
								toggle.removeClass("active");
								target.removeClass("active");
							}
							else
							{
								toggle.addClass("active");
								target.addClass("active");
							}
							return false;
						}
					}
				})(reviewLinks[i])
			}
		}
	}



	/**
	 * Activate dropdown pagebox
	 */
	function dropDownPageBox()
	{
		if(!dom.getById("dropdown_pagesize_toggle"))
		{
			return false;
		}

		var dropdownToggle = dom.getById("dropdown_pagesize_toggle"),
		menu = dom.getById("dropdown_pagesize");

		/**
		 * Handle outside click event
		 * @event
		 * @param {Event} event
		 */
		function outsideClick(event)
		{
			if (event == undefined)
			{
				event = window.event;
			}

			if (event.target == undefined)
			{
				event.target = event.srcElement;
			}

			if (event.target.parentNode.parentNode.parentNode != menu && event.target != dropdownToggle)
			{
				if (document.detachEvent)
				{
					document.detachEvent("onclick", outsideClick);
				}
				else
				{
					document.removeEventListener("click", outsideClick, false);
				}

				menu.removeClass("active");
			}
		}

		dropdownToggle.onclick = function()
		{
			if (menu.hasClass("active"))
			{
				if (document.detachEvent)
				{
					document.detachEvent("onclick", outsideClick);
				}
				else
				{
					document.removeEventListener("click", outsideClick, false);
				}

				menu.removeClass("active");
			}
			else
			{
				if (document.attachEvent)
				{
					document.attachEvent("onclick", outsideClick);
				}
				else
				{
					document.addEventListener("click", outsideClick, false);
				}

				menu.addClass("active");
			}
			return false;
		}
	}



	/**
	 * Activate ajaxified rating selector
	 */
	function ratingSelector()
	{
		if (!dom.getById("review_add"))
		{
			return false;
		}

		if (!dom.getById("review_add").getElementsByTagName("select"))
		{
			return false;
		}

		// Descriptions of rating values
		var descriptions = ["", "Zeer slecht", "Matig", "Voldoende", "Goed", "Perfect"],
			ratingSelects = dom.getById("review_add").getElementsByTagName("select"),
			i = ratingSelects.length,
			ratingSelectors = new Array();

		while (i--)
		{
			ratingSelectors[i] = new activateSelect(ratingSelects[i],ratingSelects[i].id);
		}

		/**
		 * Activate Selector
		 * @param {Object} select The selectbox
		 * @param {String} id The id
		 * @return {Object} hiddenField
		 */
		function activateSelect(select,id)
		{
			var ratingSelector = dom.create(
					"div",
					{
						className	: "ratingselector"
					},
					null
					),
				description	= dom.create(
					"div",
					{
						className: "ratingdescription"
					},
					null
					),
				descriptiontext = dom.createText(""),
				hiddenField	= dom.create(
					"input",
					{
						type	: "hidden",
						name	: select.name,
						id		: id,
						value	: select.options[select.selectedIndex].value
					},
					null
				);

			ratingSelector.style.backgroundPosition = -(80 - (hiddenField.value * 16)) + "px 0";
			ratingSelector.appendChild(hiddenField);

			for (var i = 1; i <= 5; i++) 
			{
				var star = dom.create(
					"a",
					{
						href		: "#",
						title		: i + "/5",
						onmouseover	: mouseOver,
						onmouseout	: mouseOut,
						onclick		: mouseClick
					},
					[i]
				);
				ratingSelector.appendChild(star);
			}

			ratingSelectorParent = select.parentNode;
			ratingSelectorParent.replaceChild(ratingSelector, select);
			
			description.appendChild(descriptiontext);
			ratingSelectorParent.appendChild(description);

			/**
			 * mouseOver function
			 */
			function mouseOver() {
				this.parentNode.style.backgroundPosition = -(80 - (this.firstChild.nodeValue * 16)) + "px 0";
				this.parentNode.parentNode.lastChild.firstChild.nodeValue = descriptions[this.firstChild.nodeValue];
			}

			/**
			 * mouseout function
			 */
			function mouseOut() {
				this.parentNode.style.backgroundPosition = -(80 - (this.parentNode.firstChild.value * 16)) + "px 0";
				this.parentNode.parentNode.lastChild.firstChild.nodeValue =  descriptions[this.parentNode.firstChild.value];
			}

			/**
			 * mouseClick function
			 */
			function mouseClick() {
				this.parentNode.firstChild.value = this.firstChild.nodeValue;
				return false;
			}
			
			return hiddenField;
		}
	}



	/**
	 * Activate Pros cons toggle
	 */
	function toggleProsCons()
	{
		if (!dom.getById("pros_cons_collapse"))
		{
			return false;
		}

		dom.getById("pros_cons_collapse").onclick = function(){
			var toggle = dom.extend(this),
			target = dom.getById(toggle.href.substr(toggle.href.indexOf("#") + 1));

			if (target) 
			{
				if (toggle.hasClass("active")) 
				{
					toggle.removeClass("active");
					target.removeClass("active");
				}
				else 
				{
					toggle.addClass("active");
					target.addClass("active");
				}
			}
			return false;
		}
	}

	/**
	 * Activate images toggle
	 */
	function toggleImages()
	{
		if (!dom.getById("images_collapse"))
		{
			return false;
		}

		dom.getById("images_collapse").onclick = function(){
			var toggle = dom.extend(this),
			target = dom.getById(toggle.href.substr(toggle.href.indexOf("#") + 1));
	
			if (target) {
				if (toggle.hasClass("active")) {
					toggle.removeClass("active");
					target.removeClass("active");
				} else {
					toggle.addClass("active");
					target.addClass("active");
				}
			}
			return false;
		}
	}



	/**
	 * The reviewimages handler
	 */
	function reviewImagesHandler()
	{
		if (!dom.getById("imageuploadblock"))
		{
			return false;
		}

		var imageUploadBlock = dom.getById("imageuploadblock"),
			imageUploads = new Array(),
			imageUploadFilefields = new Array(),
			activeUploadfields = 1,
			numberOfUploadFields = controller.getParameter("numberOfUploadfields");

		for (var i=1; i <= numberOfUploadFields; i++)
		{
			uploads[i-1] = false;
			imageUploads[i-1] = dom.getById("imageupload_"+i);
			imageUploadFilefields[i-1] = dom.getById("imageupload_filename_"+i);
			imageUploadFilefields[i-1].onchange = uploadFile;
			dom.getById("imageupload_delete_"+i).onclick = uploadRemove;
		}

		//  Image upload add new input
		dom.getById("imageupload_add").onclick = function()
		{
			// Activate next one
			for (var i=0; i < imageUploads.length; i++)
			{
				if (!imageUploads[i].hasClass("active"))
				{
					// Move to end
					imageUploads[i].parentNode.insertBefore(imageUploads[i], this);

					// Activate
					imageUploads[i].addClass("active");
					break;
				}
			}

			// Re-assign numbers (text)
			activeUploadfields = labelUploadfields();
			
			// Remove 'add' button if max uploads reached
			if (!(activeUploadfields < imageUploads.length))
			{
				dom.getById("imageupload_add").removeClass("active");
			}

			return false;
		}

		// 'Afbeelding 1', etc
		function labelUploadfields()
		{
			var numberLabel = 0;
			var uploadHeaders = imageUploadBlock.getElementsByTagName("h3");

			for (var i=0; i < uploadHeaders.length; i++)
			{
				if (uploadHeaders[i].parentNode.parentNode.hasClass("active")) {
					numberLabel++;
					uploadHeaders[i].firstChild.nodeValue = "Afbeelding "+numberLabel;
				}
			}
			return numberLabel;
		}

		// Image upload remove
		function uploadRemove()
		{
			var id = this.id.toString();
				id = id.substr(id.length-1);

			var iframeId = "imagedelete_iframe_"+id;

			// Deactivate
			if (activeUploadfields > 1)
			{	
				dom.getById("imageupload_"+id).removeClass("active");
			}
			else
			{
				// Reactivate send button (failsafe)
				uploadsInProgress = 0;
				dom.getById("review_send_button").removeClass("disabled");
			}

			// Empty all fields
			dom.getById("imageupload_filename_"+id).value = "";
			dom.getById("imageupload_title_"+id).value = "";
			dom.getById("imageupload_description_"+id).value = "";
			dom.getById("styled_filename_"+id).value = "";

			// remove loading icon
			dom.getById("imageupload_preview_"+id).removeClass("active");

			// remove thumb or error if any
			var thumbParent = dom.getById("imageupload_preview_"+id);
			while (thumbParent.firstChild)
			{
				thumbParent.removeChild(thumbParent.firstChild);
			}

			// create iframe for delete url
			var postFrame = dom.create(
				"iframe",
				{
					id	: iframeId,
					src : "/images/customerimageupload.php?id="+id+"&remove=1"
				},
				null
			);
			postFrame.style.display = 'none';
			document.body.appendChild(postFrame);

			// Re-assign numbers (text)
			activeUploadfields = labelUploadfields();
			
			// Activate 'add' button if needed
			imageAddButton = dom.getById("imageupload_add");
			if (!imageAddButton.hasClass("active"))
			{
				imageAddButton.addClass("active");
			}

			return false;
		}
		
		// Image asynchronous uploader (onchange)
		function uploadFile()
		{
			var id = this.id.toString();
				id = id.substr(id.length-1);

			var iframeId = "imageupload_iframe_"+id;

			// Set upload in progress
			uploads[id-1] = true;
			uploadsInProgress++;

			// remove thumb or error if any
			var thumbParent = dom.getById("imageupload_preview_"+id);
			while (thumbParent.firstChild)
			{
				thumbParent.removeChild(thumbParent.firstChild);
			}

			// Deactivate send button
			dom.getById("review_send_button").className = "disabled";

			// Update styled input
			dom.getById("styled_filename_"+id).value = this.value;
			dom.getById("imageupload_preview_"+id).addClass("active");

			// Create a new form to submit this file to the iframe
			var f = dom.create(
				"form",
				{
					action		: "/images/customerimageupload.php?id="+id+"&size=94&rnd="+Math.random(),
					encoding 	: "multipart/form-data",
					id			: "form"+id,
					target		: iframeId,
					method		: "post"
				},
				null
			);
			f.style.display = "none";

			// create iframe. In IE it only works by using innerHTML
			if (document.all && navigator.userAgent.indexOf('Opera')== -1)
			{
				f.innerHTML = "<iframe id='"+iframeId+"' name='"+iframeId+"'></iframe>";
			}
			else
			{
				var postFrame = dom.create(
					"iframe",
					{
						id		: iframeId
					},
					null
					);
				postFrame.name = postFrame.id;
				postFrame.style.display = 'none';
				f.appendChild(postFrame);
			}

			document.body.appendChild(f);

			// Add file to the new form
			f.appendChild(this);

			// Submit the file
			f.submit();

			// Place file input back
			dom.getById("file_upload_"+id).appendChild(this);
		}

		// before form submit, remove the 'real' inputs so files are not submitted with the main form
		function detachFileInputs()
		{
			for (var i=0; i<imageUploads.length; i++)
			{
				imageUploadFilefields[i].parentNode.removeChild(imageUploadFilefields[i]);
			}
			return false;
		}
	}



	/**
	 * Delete finished images
	 * @param {Number} id the image id
	 */
	function deleteFinished(id)
	{
		if (uploads[id-1])
		{
			uploads[id-1] = false;
		}

		// remove form and iframe
		var iframe = dom.getById("imagedelete_iframe_"+id, true);
		if (iframe.parentNode)
		{
			iframe.parentNode.removeChild(iframe);
		}
	}



	/**
	 * Upload the finished image
	 * @param {Number} id the image id
	 * @param {Number} error the error id if not false
	 */
	function uploadFinished(id, error)
	{
		var iframeId = "imageupload_iframe_"+id;
		
		if (uploadsInProgress > 0)
		{
			uploadsInProgress--;
		}
		else
		{
			uploadsInProgress = 0;
		}

		// remove form and contents (iframe)
		var f = dom.getById("form"+id, true);

		if (f.parentNode)
		{
			f.parentNode.removeChild(f);
		}

		if (error === false)
		{
			// show thumb
			var thumb = dom.create(
				"img",
				{
					src	: "/images/customerimageupload.php?id="+id+"&display=1&size=94&rnd="+Math.random()
				},
				null
			);
			dom.getById("imageupload_preview_"+id).appendChild(thumb);
		}
		else
		{
			var errorimg = dom.create("img");
			
			switch (error) {
				case 1:
					errorimg.src = "/images/default/uploaderror_type.png";
					break;
				case 2:
					errorimg.src = "/images/default/uploaderror_size.png";
					break;
				case 3:
				default:
					errorimg.src = "/images/default/uploaderror_path.png";
					break;
			}
			dom.getById("imageupload_preview_"+id).appendChild(errorimg);
		}

		// reactivate send button
		if (uploadsInProgress == 0)
		{
			dom.getById("review_send_button").removeClass("disabled");
		}
	}



	/**
	 * Show the reviewmailer validation
	 */
	function showReviewMailer()
	{
		if (!dom.getById("review_add"))
		{
			return false;
		}

		if (!dom.getById("review_add").getFirstByTagName("form"))
		{
			return false;
		}

		var form 	= dom.getById("review_add").getFirstByTagName("form");
		reviewMailer = new ReviewMailer(form);
	}



	/**
	 * Activate the review vote
	 */
	function activateReviewVoter() 
	{
		if (!dom.getById("reviews"))
		{
			return false;
		}

		var elements = dom.getById("reviews").getElementsByTagName("div");

		for (var i = 0; i < elements.length; i++)
		{
			dom.extend(elements[i]);
			if(elements[i].hasClass("hreview"))
			{
				var reviewId = elements[i].id.replace("review_","");
				if(dom.getById("reviewvote_" + reviewId + "_yes"))
				{
					dom.getById("reviewvote_" + reviewId + "_yes").onclick = (function(reviewId){
						return function()
						{
							var socket = new Socket();
							dom.getById("reviewvote_" + reviewId + "_yes").addClass("disabled");
							dom.getById("reviewvote_" + reviewId + "_no").addClass("disabled");
							dom.getById("reviewvote_" + reviewId + "_yes").onclick = function(){return false};
							dom.getById("reviewvote_" + reviewId + "_no").onclick = function(){return false};
							dom.getById("reviewvote_" + reviewId + "_buttons").appendChild(
								dom.create(
									"span",
									{
										className : "loading"
									},
									[]
								)
							);
							socket.request(
							"#",
								{
									reviewvoter : (new Date()).getTime(),
									save_vote	: "1",
									reviewid	: reviewId,
									vote		: "Y"
								},true,true
							);
							voteHandler(socket, reviewId, "Y");
							return false;
						}
					})(reviewId);
				}
				if(dom.getById("reviewvote_" + reviewId + "_no"))
				{
					dom.getById("reviewvote_" + reviewId + "_no").onclick = (function(reviewId){
						return function() {
							var socket = new Socket();
							dom.getById("reviewvote_" + reviewId + "_yes").addClass("disabled");
							dom.getById("reviewvote_" + reviewId + "_no").addClass("disabled");
							dom.getById("reviewvote_" + reviewId + "_yes").onclick = function(){return false};
							dom.getById("reviewvote_" + reviewId + "_no").onclick = function(){return false};
							dom.getById("reviewvote_" + reviewId + "_buttons").appendChild(
								dom.create(
									"span",
									{
										className : "loading"
									},
									[]
								)
							);
							socket.request(
							"#",
								{
									reviewvoter : (new Date()).getTime(),
									save_vote	: "1",
									reviewid	: reviewId,
									vote		: "N"
								},true,true
							);
							voteHandler(socket, reviewId, "N");
							return false;
						}
					})(reviewId);
				}
			}
		}
	}



	/**
	 * Review Votehandler
	 * @param {Socket} socket
	 * @param {Number} reviewId
	 * @param {String} vote Y for yes and N for No
	 */
	function voteHandler(socket, reviewId, vote)
	{
		socket.addEventListener(Socket.LOADED, function(event)
		{
			if (socket.getStatus() == 200)
			{
				var voteParent = dom.getById("reviewvote_" + reviewId + "_buttons");
				while (voteParent.firstChild)
				{
					voteParent.removeChild(voteParent.firstChild);
				}
				var voteText = dom.getById("reviewvote_" + reviewId + "_text");
				while (voteText.firstChild)
				{
					voteText.removeChild(voteText.firstChild);
				}

				// Update count
				var voteCountText = dom.getById("reviewvotes_"+reviewId);
				if (voteCountText.childNodes.length > 1)
				{
					if (vote == "Y")
					{
						votePos = dom.getById("reviewvotes_pos_"+reviewId);
						votePos.replaceChild
						(
							dom.createText(parseInt(votePos.firstChild.nodeValue)+1),
							votePos.firstChild
						);
					}
					voteTotal = dom.getById("reviewvotes_total_"+reviewId);
					voteTotal.replaceChild(
						dom.createText(parseInt(voteTotal.firstChild.nodeValue)+1),
						voteTotal.firstChild
					);
				}
				else
				{
					while (voteCountText.firstChild)
					{
						voteCountText.removeChild(voteCountText.firstChild);
					}
					voteCountText.appendChild(
						dom.create(
							"span",
							{
								className : "pipe"
							},
							["|"]
						)
					);
					if (vote == "Y") {
						voteCountText.appendChild(dom.createText("behulpzaamheid: 1 van 1"));
					} else {
						voteCountText.appendChild(dom.createText("behulpzaamheid: 0 van 1"));
					}
					voteCountText.appendChild(
						dom.create(
							"span",
							{
								className : "pipe"
							},
							["|"]
						)
					);
				}

				voteText.appendChild(dom.createText(getVousOuTu("Uw", "Je") + " keuze is opgeslagen. Hartelijk dank voor " + getVousOuTu("uw", "je") + " bijdrage!"));
			}
			else if(socket.getStatus() == 500)
			{
				var voteParent = dom.getById("reviewvote_" + reviewId + "_buttons");
				while (voteParent.firstChild)
				{
					voteParent.removeChild(voteParent.firstChild);
				}
				var voteText = dom.getById("reviewvote_" + reviewId + "_text");
				while (voteText.firstChild)
				{
					voteText.removeChild(voteText.firstChild);
				}
				voteText.appendChild(dom.createText(getVousOuTu("U heeft", "Je hebt") + " deze review al eerder beoordeeld"));
			}
			else
			{
				var voteParent = dom.getById("reviewvote_" + reviewId + "_buttons");
				while (voteParent.firstChild)
				{
					voteParent.removeChild(voteParent.firstChild);
				}
				var voteText = dom.getById("reviewvote_" + reviewId + "_text");
				while (voteText.firstChild)
				{
					voteText.removeChild(voteText.firstChild);
				}
				voteText.appendChild(dom.createText(getVousOuTu("Uw", "Je") + " stem kon niet worden opgeslagen"));
			}
			return null;
		});	
	}



	/**
	 * Activate the commentfield
	 */
	function activateCommentForm()
	{
		if(!dom.getById("comment_add"))
		{
			return false;
		}

		if(!dom.getById("comment_add").getFirstByTagName("form"))
		{
			return false;
		}

		var form = dom.getById("comment_add").getFirstByTagName("form");		

		var reviewCommentForm			= new Form(form),
			reviewCommentFormRows		= new CommentFormRows(),
			reviewCommentFormNotices	= new CommentFormNotices();

		reviewCommentForm.addEventListener(Form.FIELD_ADDED, reviewCommentFormRows.add);
		reviewCommentForm.addEventListener(Form.VALIDATION_COMPLETE, reviewCommentFormNotices.update);

		// Name
		var commentNameField = new InputField(dom.getById("commentname"));
			commentNameField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " naam  niet ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + commentNameField.getElement().id, onclick: commentNameField.focus}, ["naam"]), " niet ingevuld"])));
			commentNameField.addEventListener(Field.VALIDATION_COMPLETE, reviewCommentFormRows.update);
			reviewCommentForm.addField(commentNameField);

		// E-mail address
		var commentEmailAddressField = new InputField(dom.getById("commentemail"));
			commentEmailAddressField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " e-mailadres niet ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + commentEmailAddressField.getElement().id, onclick: commentEmailAddressField.focus}, ["e-mailadres"]), " niet ingevuld"])));
			commentEmailAddressField.addRequirement(new FormatRequirement(FormatRequirement.EMAIL_ADDRESS, new Notice(getVousOuTu("U heeft", "Je hebt") + " geen geldig e-mailadres ingevuld", [getVousOuTu("U heeft", "Je hebt") + " geen geldig ", dom.create("a", {href : "#" + commentEmailAddressField.getElement().id, onclick: commentEmailAddressField.focus}, ["e-mailadres"]), " ingevuld"])));
			commentEmailAddressField.addEventListener(Field.VALIDATION_COMPLETE, reviewCommentFormRows.update);
			reviewCommentForm.addField(commentEmailAddressField);

		// Review
		var commentReviewField = new InputField(dom.getById("commenttext"));
			commentReviewField.addRequirement(new FormatRequirement(FormatRequirement.NOT_EMPTY, new Notice(getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " reactie niet ingevuld", [getVousOuTu("U heeft", "Je hebt") + " " + getVousOuTu("uw", "je") + " ", dom.create("a", {href : "#" + commentReviewField.getElement().id, onclick: commentReviewField.focus}, ["reactie"]), " niet ingevuld"])));
			commentReviewField.addEventListener(Field.VALIDATION_COMPLETE, reviewCommentFormRows.update);
			reviewCommentForm.addField(commentReviewField);

		//onsumbit function
		form.onsubmit = function()
		{
			if (reviewCommentForm.validate() == true)
			{
				return true;
			}
			return false;
		}

		// Highlight form rows
		$(document).ready(function(){
			rowHighlighting($("#comment_add form")); //Marijn edit: refactor and jquery solotion
		})
	}



	/**
	 * Add or update the comment form rows
	 */
	function CommentFormRows()
	{
		var fields = {};

		this.add		= add;
		this.update		= update;
		this.loading	= loading;

		function add(event)
		{
			if (event.target in fields == false && (event.target instanceof InputField || event.target instanceof SelectField || event.target instanceof DateField))
			{
				var field = (fields[event.target] = event.target);

				// Get the row
				field.row = dom.extend(field.getElement().parentNode);

				if (field.row.hasClass("validation") == false)
				{
					field.row.addClass("validation");

					// Create and append notifier
					field.notifier = dom.create("span", {className : "validation"}, [
						dom.create("img", {src : "/images/default/validation_neutral_icon.png"})
					]);

					field.row.appendChild(fields[field].notifier);

					// Set notices
					field.failedNotice = null;
					field.passedNotice = null;

					// Validate (if the field has a value)
					if ((event.target instanceof InputField || event.target instanceof SelectField || event.target instanceof DateField) && field.getElement().value != "")
					{
						field.validate(Field.VALIDATION_TRIGGER_FIELD_ADDED);
					}
				}
			}
		}

		function update(event)
		{
			var field = fields[event.target];

			if (field == undefined)
			{
				throw new Error("Unknown field.");
			}

			// If there's a notice present, remove it
			if (field.notifier.lastChild && field.notifier.lastChild.nodeType == 3)
			{
				field.notifier.removeChild(field.notifier.lastChild);
			}

			// Clear the classes, if present
			field.row.removeClass("failed");
			field.row.removeClass("passed");

			// Validation failed, update the notifier
			if (field.getValid() == false)
			{
				field.passedNoticeNotice = null;

				if (field.failedNotice == null || field.getValidationTrigger() == Field.VALIDATION_TRIGGER_BLUR || field.getValidationTrigger() == Field.VALIDATION_TRIGGER_CHANGE || field.getValidationTrigger() == Field.VALIDATION_TRIGGER_SUBMIT)
				{
					if (field.getFailedNotice() != null)
					{
						field.failedNotice = field.getFailedNotice().getPlainText();
					}
				}

				field.row.addClass("failed");

				field.notifier.getFirstByTagName("img").src = "/images/default/validation_failed_icon.png";

				if (field.failedNotice != null)
				{
					field.notifier.appendChild(dom.createText(field.failedNotice));
				}
			}
			// Passed validation
			else if (field.getValid() == true)
			{
				field.failedNotice = null;

				if (field.getPassedNotice() != null)
				{
					field.passedNotice = field.getPassedNotice().getPlainText();
				}

				field.row.addClass("passed");

				field.notifier.getFirstByTagName("img").src = "/images/default/validation_passed_icon.png";

				if (field.passedNotice != null)
				{
					field.notifier.appendChild(dom.createText(field.passedNotice));
				}
			}
			// No validation required
			else if (field.getValid() == null)
			{
				field.notifier.getFirstByTagName("img").src = "/images/default/validation_neutral_icon.png";
			}
		}

		function loading(event)
		{
			var field = fields[event.target];

			if (field == undefined)
			{
				throw new Error("Unknown field.");
			}

			if (event.type == Field.VALIDATION_STARTED)
			{
				field.row.addClass("loading");
			}
			else if (event.type == Field.VALIDATION_COMPLETE)
			{
				field.row.removeClass("loading");
			}
		}
	}



	/**
	 * Comment Form Notices after validation
	 */
	function CommentFormNotices()
	{
		// Private
		var list = dom.create("ul", {className : "errors"});

		// Public
		this.update = update;

		/**
		 * clear errorlist
		 */
		function clear()
		{
			list.remove();

			while (list.firstChild) 
			{
				list.removeChild(list.firstChild);
			}
		}

		/**
		 * on update make error list if notices exist
		 */
		function update(event)
		{
			clear();

			var notices = event.target.getFailedNotices();

			if (notices.length > 0)
			{
				for (var i = 0; i < notices.length; i++)
				{
					list.appendChild(dom.create("li", null, notices[i].getHTML()));
				}

				var parentContainer = dom.getById("reaction_send_button");
				parentContainer.insertBefore(list,dom.getById("reaction_send_button").getFirstByTagName("input"));
			}
		}
	}

	/**
	 * Show the customer images gallery using an popupBox
	 * @param {Number} productId The product ID.
	 * @param {Number} reviewId The review ID.
	 * @param {Number} imageId The image ID.
	 * @param {Number} currentImage The current image ID.
	 * @throws {Invalid Argument} When reviewId is missing or not a number
	 * @throws {Invalid Argument} When currentImage is missing or not a number
	 */
	function showCustomerImageGallery(event, productId, reviewId, currentImage)
	{
		if (event == undefined)
		{
			event = window.event;
		}
		if (event.target == undefined)
		{
			event.target = event.srcElement;
		}
		if (typeof reviewId != "number") 
		{
			throw new Error("Invalid argument: reviewId is missing or not a number");
		}
		if (typeof currentImage != "number") 
		{
			throw new Error("Invalid argument: currentImage is missing or not a number");
		}

		var socket			= new Socket(),
			requestResult	= null,
			popupBox		= null,
			userAgent		= new UserAgent(),
			storeId 		= controller.getParameter("shopid"),
			images,fullSize,thumbnails,enlargeLink;

		if (userAgent.getUserAgent() == UserAgent.UA_MSIE && userAgent.getVersion() == "6.0")
		{
			//location.hash is changed to "#" to force IE6 to display the page from the top after using the back button.
			location.hash = "#";
		}

		popupBox = new PopupBox(
			"Even geduld " + getVousOuTu("alstublieft", "alsjeblieft") + "...",
			[
				dom.create(
					"div",
					{
						className : "popupbox_content_loading"
					},
					[
						"Wordt geladen..."
					]
				)
			],
			"customer_image_gallery"
		);

		socket.addEventListener(Socket.LOADED, function(event)
		{    
			if (socket.getStatus() == 200)
			{
				// Evaluate the response
				try
				{
					eval(event.target.getResponseText());
				}
				catch(error)
				{
					return null;
				}

				requestResult = result;

				popupBox.setTitle(requestResult.reviewTitle);
				popupBox.setContent(requestResult.content);
				images = requestResult.images;
				fullSize = dom.getById("customer_image_gallery_fullsize",true);
				thumbnails = dom.getById("customer_image_gallery_thumbnails",true);
				enlargeLink = dom.getById("image_enlarge",true);
			}
			else
			{
				popupBox.setTitle("De informatie kon niet worden geladen");
				popupBox.setContent([
					dom.create(
						"div",
						{
							className : "popupbox_content_loading_error"
						},
						[
							"Helaas kon de informatie niet worden geladen. Onze excuses voor het ongemak."
						]
					)
				], true);
			}

			return null;
		});

		socket.request(
			"/review/" + reviewId + "/" + productId + "/",
			{
				customergallery : (new Date()).getTime(),
				currentimage 	: currentImage
			}
		);

		popupBox.show();

		previousImage = function(){
			if (currentImage == 0)
			{
				currentImage = images.length - 1;
			}
			else
			{
				currentImage--;
			}
			setCurrent(currentImage);
			return false;
		}

		nextImage = function(){
			if (currentImage == images.length - 1)
			{
				currentImage = 0;
			}
			else
			{
				currentImage++;
			}
			setCurrent(currentImage);
			return false;
		}

		// Show the thumbnail full size
		zoomImage = function(event)
		{
			dom.extend(event);
			var clickedImage = event.id.substr(30);
			if (clickedImage != currentImage)
			{
				currentImage = clickedImage;
				setCurrent(currentImage);
			}
			return false;
		}

		function setCurrent(currentImage)
		{
			// Clear the "current" class from the other thumbnails and set it to this thumbnail
			for (var i = 0, thumbnailsLength = thumbnails.childNodes.length; i < thumbnailsLength; i++)
			{
				dom.extend(thumbnails.childNodes[i]);
				thumbnails.childNodes[i].removeClass("current");
			}

			dom.extend(dom.getById("customer_image_thumbnail_link_"+currentImage,true).parentNode);
			dom.getById("customer_image_thumbnail_link_"+currentImage,true).parentNode.addClass("current");
			dom.getById("customer_image_gallery_fullsize",true).href = "/images/customerimage.php?id=" + images[currentImage].imageId;
			dom.getById("customer_image_gallery_image_title",true).innerHTML = images[currentImage].imageTitle;
			dom.getById("customer_image_gallery_image_description",true).innerHTML = images[currentImage].imageDescription;
			if(dom.getById("image_enlarge"))
			{
				dom.getById("image_enlarge",true).href = "/images/customerimage.php?id=" + images[currentImage].imageId;
			}
			fullSize.firstChild.src = "/images/customerimage.php?id=" + images[currentImage].imageId + "&dimensionid=35&shopid="+storeId;
		}

		return null;
	}
}

// Inheritance
Review.prototype = new Page();
controller.setPageObject(review);