if (!Effect)
	console.log("Scriptaculous isn't loaded.");

var OP = (navigator.userAgent.indexOf('Opera') != -1) ? true : false;
var IE = (navigator.userAgent.indexOf('MSIE') != -1 && !OP) ? true : false;
var GK = (navigator.userAgent.indexOf('Gecko') != -1) ? true : false;
var SAF = (navigator.userAgent.indexOf('Safari') != -1) ? true : false;


var onloadHooks = [], mouseX, mouseY;

//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Scriptaculous Extensions
//////////////////////////////////////////////////////////////////////////////////////////////////////////

Effect.PhaseIn = function(element) {
  element = $(element);
  new Effect.SlideDown(element, arguments[1] || {queue: 'front'});
  new Effect.Appear(element, arguments[2] || arguments[1] || {});
};

Effect.PhaseOut = function(element) {
  element = $(element);
  new Effect.Fade(element, arguments[1] || {});
  new Effect.BlindUp(element, arguments[2] || arguments[1] || {});
};

Effect.Phase = function(element) {
	element = $(element);
	if (element.style.display == 'none')
		new Effect.PhaseIn(element, arguments[1] || {}, arguments[2] || arguments[1] || {});
	else
		new Effect.PhaseOut(element, arguments[1] || {}, arguments[2] || arguments[1] || {});
};

function swapElements(el1, el2)
{
	new Effect.Parallel( 
		[	new Effect.SlideDown(el2, {sync: true }),
			new Effect.SlideUp(el1, {sync: true })
		], {duration:0.4});
}

// returns true if now visible, false if now hidden
function animatedToggleVisible(elementID)
{
	var el = $(elementID);
	var isDisplayed = el.style.display != 'none';
	if (isDisplayed)
		Effect.PhaseOut(el, {duration:0.25});
	else
		Effect.PhaseIn(el, {duration:0.25});

	return !isDisplayed;
}
function showReply(replyObjectID, respondingTo, respondingToField)
{
	var replyObject = $(replyObjectID);
	
	// if not visible show it
	var isDisplayed = replyObject.style.display != 'none';
	if(!isDisplayed)
		animatedToggleVisible(replyObjectID);
		
	// apply the respondingTo ID
	respondingToField = $(respondingToField);
	respondingToField.value=respondingTo;
	
	return false;
}
function showPreview(target, source, parent, appID)
{
	// these techniques give IE some trouble ...
	// revert to getElementById
	/*
	var el = $(target);
	var el2 = $(source);
	var el3 = $(parent);
	*/
	
	var el = document.getElementById(target);
	var el2 = document.getElementById(source);
	var el3 = document.getElementById(parent);
	
	var content = nl2br(htmlspecialchars(el2.value));
	
	// display the preview panel
	el3.style.display= '';
	
	//innerText is a trade off
	// if will render the converted elements into html and properly display the line breaks
	// however if innerText, or textContent is used, it displays only the literal HTML Code
	// and will require some browser tests
	// so innerHTML is used instead
	el.innerHTML = content;
		
	return false;
}

function nl2br(input)
{
	var breakChr = "<br />";
	return (input + '').replace(/([^>]?)\n/g, '$1'+ breakChr +'\n');
}
function htmlspecialchars(p_string) {
	p_string = p_string.replace(/&/g, '&amp;');
	p_string = p_string.replace(/</g, '&lt;');
	p_string = p_string.replace(/>/g, '&gt;');
	p_string = p_string.replace(/"/g, '&quot;');
	p_string = p_string.replace(/'/g, '&#039;');
	
	return p_string;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Modal dialogs
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function confirmBan(action, actionDescription, deleteURL, redirectType)
{
	startDialog(
		'<h1>Are you sure?</h1>\
		<div class="dialog-content">Are you sure you want to ' + actionDescription + '?</div><br/>\
		<form name="ModalDeleteForm" action="' + deleteURL + '" method="post">\
			<button type="button" onclick="finishDialog();" class="dialog-submit">Cancel</button>\
			<button type="submit" class="dialog-submit">' + action + '</button>\
			<input type="hidden" name="delete" value="yes" />\
			<input type="hidden" name="redirect" value="' + redirectType + '" />\
		</form>');

	return false;
}

function confirmDelete(itemToBeDeleted, deletionDescription, deleteURL, redirectType)
{
	startDialog(
		'<h1>Are you sure?</h1>\
		<div class="dialog-content">Are you sure you want to delete ' + deletionDescription + '?</div><br/>\
		<form name="ModalDeleteForm" action="' + deleteURL + '" method="post">\
			<button type="button" onclick="finishDialog();" class="dialog-submit">Cancel</button>\
			<button type="submit" class="dialog-submit">Delete ' + itemToBeDeleted + '</button>\
			<input type="hidden" name="delete" value="yes" />\
			<input type="hidden" name="redirect" value="' + redirectType + '" />\
		</form>');

	return false;
}

function confirmUnsubscribe(projectName, pointCount, unsubscribeURL)
{
	startDialog(
		'<h1>Are you sure?</h1>\
		<div class="dialog-content">Are you sure you want to unsubscribe from ' + projectName + '? ' +
		'You will ' + pointCount + ' not be able to submit tickets unless you re-subscribe.</div><br/>\
		<form name="ModalDeleteForm" action="' + unsubscribeURL + '" method="post">\
			<button type="button" onclick="finishDialog();" class="dialog-submit">Cancel</button>\
			<button type="submit" class="dialog-submit">Unsubscribe</button>\
			<input type="hidden" name="delete" value="yes" />\
		</form>');

	return false;
}
function loginForm(loginURL, siteName)
{
	startDialog(
		'<h1>Login to ' + siteName + '</h1>\
		<div class="dialog-content">Please enter your username and password. <a href="/users/forgot">Forgot your password?</a></div><br/>\
		<form name="ModalLoginForm" id="ModalLoginForm" action="' + loginURL + '" method="post">\
			<label><strong>Username:</strong></label>\
			<input type="text" name="username" /><br/>\
			<label><strong>Password:</strong></label>\
			<input type="password" name="password" /><br/><br/>\
			<input type="checkbox" name="keepLoggedIn" id="keepLoggedIn" checked="checked" /><label style="display: inline" for="keepLoggedIn">Keep me logged in</label><br/><br/>\
			<button type="button" onclick="finishDialog();" class="dialog-submit">Cancel</button>\
			<button type="submit" class="dialog-submit">Log In</button>\
		</form>');
	
	setTimeout("document.ModalLoginForm.username.focus();", 50);
	return false;
}

function confirmDeleteAccount(deleteURL)
{
	startDialog(
		'<h1>Are you sure?</h1>\
		<div class="dialog-content">Are you sure you want to delete your '+_SiteName+' account?\
		Your account, personal data, points, and rewards will all be permenantly deleted, and <strong class="holycrap">you will not be able to recover your account.</strong></div><br/>\
		<form name="ModalDeleteForm" action="' + deleteURL + '" method="post">\
			Please enter your password as confirmation:\
			<input type="password" name="password" /><br/><br/>\
			<button type="button" onclick="finishDialog();" class="dialog-submit">Cancel</button>\
			<button type="submit" class="dialog-submit">Delete my account</button>\
			<input type="hidden" name="delete" value="yes" />\
		</form>');

	return false;
}

function screencastPopup(screencastURL, width, height, title)
{
	height += 16;
	startDialog('<div style="padding: 3px 0; color: #383838">You are watching the <strong>'+title+'</strong></div>\
		<div class="medium-image-border" style="border-bottom: none;">\
		<object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab" width="'+width+'" height="'+height+'">\
			<param name="src" value="'+screencastURL+'" />\
			<param name="controller" value="true" />\
			<param name="autoplay" value="true">\
			<object type="video/quicktime" data="'+screencastURL+'" width="'+width+'" height="'+height+'" class="mov dark-image-border">\
				<param name="controller" value="true" />\
				<param name="autoplay" value="true"/>\
				<param name="cache" value="false"/>\
				Error.\
			</object>\
		</object></div>', 'screencast');
	
	return false;
}


function startDialog(htmlContent, dialogClass)
{
	var dialog = new Element("div", {'class':'ModalDialog', 'style':'display:none;' });
	var backdrop = new Element("div", {'class':'ModalDialogBackdrop', 'style':'display:none;  height: 100%'});
	
	if (dialogClass)
		dialog.className += ' ' + dialogClass;
	
	backdrop.style.minHeight = ((!IE ? document.body.clientHeight : document.documentElement.clientHeight) + document.body.style.marginBottom) + 'px';
	
	var scrollOffsets = document.viewport.getScrollOffsets();
	dialog.style.top = scrollOffsets[1] + 'px';
	backdrop.onclick = finishDialog;
	
	dialog = dialog.update(
		'<div class="close-button"><a href="javascript:{}" onclick="return finishDialog();">\
			<img src="' + ImagesPath + '/icons/close.png" alt="Close" />\
		</a></div>' + htmlContent);
	
	$('DialogContainer').insert(backdrop);
	$('DialogContainer').insert(dialog);
	
	Effect.Appear(backdrop, {duration:0.3, to:.75});
	Effect.Appear(dialog, {duration:0.3});
}

function finishDialog()
{
	var elements = $('DialogContainer').descendants();
	
	for (var i = 0; i < elements.length; i++)
		elements[i].remove();
	
	return false;
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Form Sugar
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function selectAll(baseName)
{
	return toggleCheckboxesSelected(baseName, true);
}

function deselectAll(baseName)
{
	return toggleCheckboxesSelected(baseName, false);
}

function toggleCheckboxesSelected(baseName, selected)
{
	var elements = document.getElementsByTagName("input");
	
	for (var i = 0; i < elements.length; i++)
		if (elements[i].name.indexOf(baseName) == 0)
			elements[i].checked = selected;
	return false;
}

function setSeverityBox(boxID, severitySelector)
{
	var colors = {"lowest":"#E0FFE9", "low":"#D5F9B7", "normal":"#FCFFB5", "high":"#FABB81", "highest":"#E6767B"};
	
	var level = severitySelector.value;
	
	$('severity-box-' + boxID).style.backgroundColor = colors[level];
	severitySelector.style.backgroundColor = colors[level];
}

function loadColorChangingInputs()
{
	var inputs = document.getElementsByTagName('input');
	var textareas = document.getElementsByTagName('textarea');
	
	var handler =  function (ev) { colorChangingInputOnclick(ev.element()); };
	
	for (var i = 0; i < inputs.length; i++)
		if (inputs[i].type == 'text' || inputs[i].type == 'password')
		{
			Event.observe(inputs[i], 'blur', handler);
			Event.observe(inputs[i], 'focus', handler);
			colorChangingInputOnclick(inputs[i]);
		}
		
	for (var i = 0; i < textareas.length; i++)
		if (textareas[i].readonly != '')
		{
			Event.observe(textareas[i], 'blur', handler);
			Event.observe(textareas[i], 'focus', handler);
			colorChangingInputOnclick(textareas[i]);
		}
}

function colorChangingInputOnclick(el)
{
	Element.extend(el);
	
	if (el.hasClassName('unfocused'))
	{
		el.removeClassName('unfocused');
		el.addClassName('focused');
	}
	else
	{
		el.removeClassName('focused');
		el.addClassName('unfocused');
	}
}

function confirmReleaseAdd()
{
	var verified = true;
	verified &= BinaryAddForm.version.value.length();
	
	var inputs = document.getElementsByTagName("input")
	
	var somethingChecked = false;
	for (var i = 0; i < inputs.length; i++)
		if (inputs[i].type == 'checkbox' && inputs[i].type.checked)
		{
			somethingChecked = true;
			break;
		}
	
	verified &= somethingChecked;
	verified &= BinaryAddForm.link.value.length() && BinaryAddForm.link.value != 'http://';
	
	if (!verified)
		startDialog(
			'<h1>You must fill out the entire form</h1>\
			<div class="dialog-content">You must enter a version, URL and select at least one type of ticket\
			<button type="button" onclick="finishDialog();" class="dialog-submit">Ok</button>');
	
	return verified;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Global Hooks
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function registerOnLoadHook(action)
{
	onloadHooks[onloadHooks.length] = action;
}

function mainOnLoad()
{
	attachResizableTextAreas();
	attachToolTips();
	
	for (var i = 0; i < onloadHooks.length; i++)
		onloadHooks[i]();
	
	Event.observe(document, 'mousemove', mouseMovedTracker);
}

function mouseMovedTracker(ev)
{
	mouseX = Event.pointerX(ev);
	mouseY = Event.pointerY(ev);
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Resizable Textareas
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function attachResizableTextAreas()
{
	if (SAF)
		return;
		
	(function(){
	  var resizeTa = {
	    TAlength: 0,
	    TA: new Array(),

	    collectionToArray: function(col){
	      a = new Array();
	      for(i = 0, l = col.length; i < l; i++)
	        a[a.length] = col[i];
	      return a;
	    },

	    load: function(){

	      resizeTa.TA = resizeTa.collectionToArray(document.getElementsByTagName("textarea"));
	      var inputs;
	      inputs = document.getElementsByTagName("input");
	      for(var i = 0, l = inputs.length; i < l; i++){
	        if(
	          !inputs[i].hasAttribute("type") ||
	          inputs[i].getAttribute("type") == "text" ||
	          inputs[i].getAttribute("type") == "password"
	        ){
	          resizeTa.TA.push(inputs[i]);
	        }
	      }
	    },

	    init: function(aEvent){
	      resizeTa.load();

	      resizeTa.TAlength = resizeTa.TA.length;
	      if(resizeTa.TAlength == 0){
	        return;
	      }
	      else{
	        resizeTa.rootElem = document.getElementsByTagName("html")[0];
	        var i = resizeTa.TAlength;
	        while(i--){
	          if(
	            resizeTa.TA[i].tagName.toLowerCase() == "textarea" ||
	            resizeTa.TA[i].tagName.toLowerCase() == "iframe"
	          ){
	            resizeTa.newdiv("4", "1", "gripH_", i, "w");
	            resizeTa.newdiv("1", "4", "gripV_", i, "n");
	            resizeTa.newdiv("10", "10", "gripX_", i, "se");
	          }
	          else if(resizeTa.TA[i].tagName.toLowerCase() == "select"){
	            resizeTa.newdiv("1", "4", "gripV_", i, "n");        
	          }
	          else if(resizeTa.TA[i].tagName.toLowerCase() == "input"){
	            resizeTa.newdiv("4", "1", "gripH_", i, "w");
	          }
	        }
	        resizeTa.newdiv("0", "0", "showCursor", "", "w");
	        CursorDiv = document.getElementById("showCursor");
	        CursorDiv.removeEventListener("mousedown", resizeTa.activate, true);
	        CursorDiv.style.left = "0px";
	        CursorDiv.style.top  = "0px";
	        resizeTa.posdivs();
	        window.addEventListener("resize", resizeTa.posdivs, true);
	      }
	    },

	    newdiv: function(w, h, id, nr, cu){
	      var grip = document.createElement("div");
	      grip.setAttribute("id", id + nr);
	      grip.setAttribute(
	        "style",
	        "position: absolute; z-index: 9999; width: "+w+"px; height: "+h+"px; cursor: "+cu+"-resize;"
	      );
	      grip.addEventListener("mousedown", resizeTa.activate, true);
	      resizeTa.rootElem.appendChild(grip);
	    },

	    getposition: function(i){
	      var curElem = resizeTa.TA[i];
	      var curX = curElem.offsetLeft;
	      while(curElem.offsetParent){
	        curX += curElem.offsetParent.offsetLeft;
	        curElem = curElem.offsetParent;
	      }
	      curElem = resizeTa.TA[i];
	      var curY = curElem.offsetTop;
	      while(curElem.offsetParent){
	        curY += curElem.offsetParent.offsetTop;
	        curElem = curElem.offsetParent;
	      }
	      return [curX,curY];
	    },

	    posdivs: function(){
	      var k = resizeTa.TAlength;
	      while(k--){
	        curPos = resizeTa.getposition(k);

	        // add horizontal, vertical, and corner grippies to textarea and select
	        if(
	          resizeTa.TA[k].tagName.toLowerCase() == "textarea" ||
	          resizeTa.TA[k].tagName.toLowerCase() == "iframe"
	        ){
		
				resizeTa.TA[k].style.backgroundImage = "url('/static/images/grippie.png')";
				resizeTa.TA[k].style.backgroundPosition = "bottom right";
				resizeTa.TA[k].style.backgroundRepeat = "no-repeat";
				resizeTa.TA[k].style.paddingBottom = "13px";

	          document.getElementById('gripV_'+k).style.left   = curPos[0]                               + "px";
	          document.getElementById('gripV_'+k).style.top    = curPos[1]+resizeTa.TA[k].offsetHeight-2 + "px";
	          document.getElementById('gripV_'+k).style.width  =           resizeTa.TA[k].offsetWidth -8 + "px";

	          document.getElementById('gripX_'+k).style.left   = curPos[0]+resizeTa.TA[k].offsetWidth -8 + "px";
	          document.getElementById('gripX_'+k).style.top    = curPos[1]+resizeTa.TA[k].offsetHeight-8 + "px";
	        }
	      }
	    },

	    activate: function(e){
	      resizeTa.load();
	      CursorDiv       = document.getElementById("showCursor");
	      var curTargetId = e.target.getAttribute("id").split("_");
	      curTarget       = curTargetId[0];
	      curTA_Nr        = parseInt(curTargetId[1]);
	      document.addEventListener("mouseup", resizeTa.deactivate, true);
	      switch(curTarget){
	        case "gripH": document.addEventListener("mousemove", resizeTa.resizeta_h, true); break;
	        case "gripV": document.addEventListener("mousemove", resizeTa.resizeta_v, true); break;
	        case "gripX": document.addEventListener("mousemove", resizeTa.resizeta_x, true); break;
	      }
	      CursorDiv.style.width  = resizeTa.rootElem.offsetWidth + "px";
	      CursorDiv.style.height = resizeTa.rootElem.offsetHeight + "px";
	      CursorDiv.style.cursor = e.target.style.cursor;
	    },

	    deactivate: function(){
	      document.removeEventListener("mouseup", resizeTa.deactivate, true);
	      switch(curTarget){
	        case "gripH": document.removeEventListener("mousemove", resizeTa.resizeta_h, true); break;
	        case "gripV": document.removeEventListener("mousemove", resizeTa.resizeta_v, true); break;
	        case "gripX": document.removeEventListener("mousemove", resizeTa.resizeta_x, true); break;
	      }
	      CursorDiv.style.width  = "0px";
	      CursorDiv.style.height = "0px";
	      resizeTa.posdivs();
	    },

	    resizeta_h: function(e){
	      curPos = resizeTa.getposition(curTA_Nr);
	      if(e.pageX - curPos[0] > 20){
	        resizeTa.TA[curTA_Nr].style.width = e.pageX - curPos[0] + "px";
	      }
	    },

	    resizeta_v: function(e){
	      curPos = resizeTa.getposition(curTA_Nr);
	      if(e.pageY - curPos[1] > 20){
	        resizeTa.TA[curTA_Nr].style.height = e.pageY - curPos[1] + "px";
	      }
	      if(resizeTa.TA[curTA_Nr].tagName.toLowerCase() == "select"){
	        if(e.pageY - curPos[1] < 25){
	          resizeTa.TA[curTA_Nr].setAttribute("size", 1);
	        }
	        else{
	          resizeTa.TA[curTA_Nr].setAttribute("size", 2);
	        }
	      }
	    },

	    resizeta_x: function(e){
	      curPos = resizeTa.getposition(curTA_Nr);

	      if(e.pageX - curPos[0] > 20 && e.pageY - curPos[1] > 20){
	       // resizeTa.TA[curTA_Nr].style.width  = e.pageX - curPos[0] + 2 + "px";
	        resizeTa.TA[curTA_Nr].style.height = e.pageY - curPos[1] + 2 + "px";
	      }
	      if(resizeTa.TA[curTA_Nr].tagName.toLowerCase() == "select"){
	        resizeTa.TA[curTA_Nr].setAttribute("size", 2);
	      }
	    }
	  }

	  if(document.body) resizeTa.init();
	})();
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Tickets
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function ticketEditorStatusChanged(statusSelector)
{
	if (statusSelector.value == 'rejected' && $('TicketEditorRejectionSection').style.display == 'none')
		Effect.SlideDown($('TicketEditorRejectionSection'), {'duration':0.3});
	else if (statusSelector.value != 'rejected' && $('TicketEditorRejectionSection').style.display != 'none')
		Effect.SlideUp($('TicketEditorRejectionSection'), {'duration':0.3});
}

function hideShowCrashLogEditor(el)
{
	var editorNeeded = el.value == 'highest' && el.checked;
	var editorOn = $('CrashLogEditor').style.display != 'none';

	if (editorNeeded && !editorOn)
		Effect.SlideDown($('CrashLogEditor'), {'duration':0.3});
	else if (!editorNeeded && editorOn)
		Effect.SlideUp($('CrashLogEditor'), {'duration':0.3});
}

var ticketSearchPhraseChanged = function(element, value)
{
	if (!element)
		element = new Element('div');
	
	var searching = value.length != 0;

	
	if (searching)
	{		
		element.addClassName('loading');
		
		new Ajax.Request(_BasePath + 'tickets/search/' + _currentAppID,
	        {	asynchronous:true,
				onComplete:function(request)
				{
					$('AjaxTabContent').update(request.responseText);
					$('TicketSearchPhrase').removeClassName('loading');
				/*	console.log("test");
					new Effect.PhaseOut('OriginalTabContent', {duration:.25});
					new Effect.FadeIn('AjaxTabContent', {duration:.25});
					console.log("test2");*/
					if ($('OriginalTabContent').style.display != "none" && $('AjaxTabContent').style.display == "none")
						swapElements('OriginalTabContent', 'AjaxTabContent');
					
				}, 
	       		method:'post',
				parameters:{'phrase' : value}
			});
	}
	else
	{
	//	element.removeClassName('loading');
		
	if ($('OriginalTabContent').style.display == "none" && $('AjaxTabContent').style.display != "none")
			swapElements('AjaxTabContent', 'OriginalTabContent');
		
		
	//	new Effect.phaseOut('OriginalTabContent');
		
	}
	
	

}

//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Project Creation page
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function toggleCreditBilling(el)
{
	var editorNeeded = el.value == 'credit' && el.checked;
	var editorOn = $('CreditBillingInfo').style.display != 'none';

	if (editorNeeded && !editorOn)
		Effect.SlideDown($('CreditBillingInfo'), {'duration':0.3});
	else if (!editorNeeded && editorOn)
		Effect.SlideUp($('CreditBillingInfo'), {'duration':0.3});		
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Petitions (feature requests)
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function firstSubmitButton(submitURL, attachmentURL, uploadNonce)
{	
	var resultValue = $('PetitionSearchResults').innerHTML;
	if (!resultValue.length || resultValue.indexOf('No feature requests similar to') != -1)
		return secondSubmitButton(submitURL, attachmentURL, uploadNonce);
	
	Effect.Appear('SearchWarning', {duration:0.2, queue:'front'});
	Effect.Pulsate('SearchWarning', {pulses:2, duration:0.75, from:.5, queue:'end'});
	return false;
}

function secondSubmitButton(submitURL, attachmentURL, uploadNonce)
{	
	Effect.Fade('SearchWarning', {duration:0.3, queue:'front'});
	var titleValue = $('PetitionSearchPhrase').value.replace(/"/,"\\\"");
	var uploadFrameID = "ExternalUploadForm-" + Math.floor(Math.random()*100000000);
	
	startDialog(
		'<h1>Submit Suggestion</h1><div class="dialog-content" style="overflow-y: hidden">\
			<form name="PetitionSubmissionForm" action="' + submitURL + '" method="post">\
				<input type="hidden" name="upload_nonce" value="'+ uploadNonce + '" />\
				Title:<br/>\
				<input type="text" class="long-text-field" id="PetitionTitle" name="title" value="'+titleValue+'"><br/><br/>\
				Description:<br/>\
				<textarea name="description" id="PetitionDescription" rows="4" style="width: 494px"></textarea><br/><br/>\
				<div id="PetitionAttachmentsDisclosure" class="para" style="margin-bottom: 8px"><a href="javascript:swapElements(\'PetitionAttachmentsDisclosure\',\'PetitionAttachments\');">Attach a screenshot</a><br/></div>\
				<div id="PetitionAttachments" style="display: none">\
					<iframe id="'+uploadFrameID+'" class="ExternalUploadForm" src="'+attachmentURL+'" height="40px" width="494px"></iframe><br/>\
				</div>\
				<div class="InformationalBox light" style="width: 478px">If you\'re submitting a bug, submit it as a ticket. The developer has no way to reply to suggestions.</div>\
				<button type="button" onclick="finishDialog();" class="dialog-submit">Cancel</button>\
				<button type="button" onclick="verifyPetitionForm();" class="dialog-submit">Suggest</button>\
			</form>\
		</div>');
	
	setTimeout("document.PetitionSubmissionForm.title.focus();", 50);
	return false;	
}

function verifyPetitionForm()
{
	var titleField = $('PetitionTitle'), descField = $('PetitionDescription');
	
	if (!titleField.value.length)
		titleField.addClassName('unfilled');
	else
		titleField.removeClassName('unfilled');
		
	if (!descField.value.length)
		descField.addClassName('unfilled');
	else
		descField.removeClassName('unfilled');

	if (titleField.value.length && descField.value.length)
		document.PetitionSubmissionForm.submit();
}


function vote(petitionID)
{
	$('PetitionVoteLink' + petitionID).replace(new Element("span", {'class':'light'}).update("voted"));
	new Ajax.Request(_BasePath + 'petitions/vote/' + petitionID,
		{	method:'post',
			onComplete:function(transport) { $('PetitionVoteCount' + petitionID).innerHTML = transport.responseText; }, 
			parameters:{'submit' : 1}
		});
}


var petitionSearchPhraseChanged = function(element, value)
{
	if (!element)
		element = new Element('div');
	
	var searching = value.length != 0;
	
	if ($('PetitionFirstSubmit'))
		$('PetitionFirstSubmit').disabled = (searching) ? '' : 'disabled'; 
	
	if (searching)
	{
		if ($('PetitionTypeSelector').down('td.selected'))
			$('PetitionTypeSelector').down('td.selected').removeClassName('selected'); // xxx old
			
		if ($('PetitionTypeSelector').down('li.selected'))
			$('PetitionTypeSelector').down('li.selected').removeClassName('selected');
		
		element.addClassName('loading');
	}
	else
	{
		if ($('PetitionTypeSelector').down('td.selected'))
			$('PetitionTypeSelector').down('td.selected').removeClassName('selected');// xxx old
		
		if ($('PetitionTypeSelector').down('li.selected'))
			$('PetitionTypeSelector').down('li.selected').removeClassName('selected');
		
		$('PetitionTypeSelector').down('li.' + _petitionPageType).addClassName('selected');
		$('FeatureRequestContainer').addClassName('loading');
	}
	
	
	new Ajax.Updater({success: 'PetitionSearchResults'}, _BasePath + 'petitions/search/' + _currentAppID,
        {	asynchronous:true,
			onComplete:function(request){ $('FeatureRequestContainer').removeClassName('loading'); $('PetitionSearchPhrase').removeClassName('loading');  }, 
       		method:'post',
			parameters:{'phrase' : value, 'page' : _petitionPageNumber, 'type' : _petitionPageType}
		});
}

function changeFeatureRequestPage(pageNumber)
{
	_petitionPageNumber = pageNumber;
	petitionSearchPhraseChanged(null, '');
}

function changeType(type)
{
	_petitionPageNumber = 1;
	_petitionPageType = type;
	petitionSearchPhraseChanged(null, '');
}

function modifyPetition(petitionID)
{
	$('PetitionModify' + petitionID).disabled = 'disabled';
	
	var petitionEditor = $('PetitionEditor' + petitionID);
	
	new Ajax.Request(_BasePath + 'petitions/modify/' + petitionID,
		{	method:'post',
			onComplete:function(transport) { 
				var parts = transport.responseText.split("\n\n", 3);
				$('PetitionEditor' + petitionID).innerHTML = parts[0];
				$('PetitionStatus' + petitionID).innerHTML = parts[1];
				if (parts[2].strip() == '' && $('PetitionResponseText' + petitionID).style.display == "block")
					Effect.SlideUp($('PetitionResponseText' + petitionID), {duration:0.3});
				else if (parts[2].strip() != '')
				{
					$('PetitionResponseText' + petitionID).down('div.para').innerHTML = parts[2];
					if ($('PetitionResponseText' + petitionID).style.display == "none")
						Effect.SlideDown($('PetitionResponseText' + petitionID), {duration:0.3});
				}
				 
				}, 
			parameters:{'submit' : 1, 'status' : petitionEditor.down('select').value, 'response' : petitionEditor.down('textarea').value}
		});
}

function confirmDeletePetition(petitionID)
{
	$('PetitionEditor' + petitionID).update(
		'Are you sure?\
		<button type="button" style="margin-left: 10px" onclick="deletePetition(\'' + petitionID + '\')">Delete</button>');
}


function deletePetition(petitionID)
{
	new Ajax.Request(_BasePath + 'petitions/delete/' + petitionID,
		{	method:'post',
			onComplete:function(transport)
				{
					if (transport.responseText.strip() == 'deleted')
						Effect.SlideUp($('Petition' + petitionID), {'duration':0.5});
				}, 
			parameters:{'submit' : 1}
		});	
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Tooltips
//////////////////////////////////////////////////////////////////////////////////////////////////////////
function attachToolTips()
{
	$$("label").each( function(label) {
		if (label.title)
			new Tooltip(label,  {backgroundColor: "#E0E9FC", borderColor: "#7998E0", textColor: "#000", delay:150});
	});
	
	$$("a").each( function(link) {
		if (link.title)
			new Tooltip(link,  {backgroundColor: "#E0E9FC", borderColor: "#7998E0", textColor: "#000", delay:500});
	});
	
	$$(".contextual-help", ".inline-help").each( function(span) {
		if (span.title)
			new Tooltip(span,  {backgroundColor: "#E0E9FC", borderColor: "#7998E0", textColor: "#000", delay:50, width:600, opacity:0.92});
	});
}

var Tooltip = Class.create();
Tooltip.prototype = {
	initialize: function(el, options) {
		this.el = $(el);
		this.initialized = false;
		this.setOptions(options);
		
		// Event handlers
		this.showEvent = this.show.bindAsEventListener(this);
		this.hideEvent = this.hide.bindAsEventListener(this);
		this.updateEvent = this.update.bindAsEventListener(this);
		Event.observe(this.el, "mouseover", this.showEvent );
		Event.observe(this.el, "mouseout", this.hideEvent );
		
		// Removing title from DOM element to avoid showing it
		this.content = this.el.title;
		this.el.title = "";

		// If descendant elements has 'alt' attribute defined, clear it
		this.el.descendants().each(function(el){
			if(Element.readAttribute(el, 'alt'))
				el.alt = "";
		});
	},
	setOptions: function(options) {
		this.options = {
			backgroundColor: '#999', // Default background color
			borderColor: '#666', // Default border color
			textColor: '', // Default text color (use CSS value)
			textShadowColor: '', // Default text shadow color (use CSS value)
			maxWidth: 615,	// Default tooltip width
			align: "left", // Default align
			delay: 250, // Default delay before tooltip appears in ms
			mouseFollow: false, // Tooltips follows the mouse moving
			opacity: 1, // Default tooltips opacity
			appearDuration: .25, // Default appear duration in sec
			hideDuration: .25 // Default disappear duration in sec
		};
		Object.extend(this.options, options || {});
	},
	show: function(e) {
		this.xCord = Event.pointerX(e);
		this.yCord = Event.pointerY(e);
		if(!this.initialized)
			this.timeout = window.setTimeout(this.appear.bind(this), this.options.delay);
	},
	hide: function(e) {
		if(this.initialized) {
			this.appearingFX.cancel();
			if(this.options.mouseFollow)
				Event.stopObserving(this.el, "mousemove", this.updateEvent);
			new Effect.Fade(this.tooltip, {duration: this.options.hideDuration, afterFinish: function() { Element.remove(this.tooltip) }.bind(this) });
		}
		this._clearTimeout(this.timeout);
		
		this.initialized = false;
	},
	update: function(e){
		this.xCord = Event.pointerX(e);
		this.yCord = Event.pointerY(e);
		this.setup();
	},
	appear: function() {
		// Building tooltip container
		this.tooltip = Builder.node("div", {className: "tooltip", style: "display: none;" }, [
			Builder.node("div", {className:"xtop"}, [
				Builder.node("div", {className:"xb1", style:"background-color:" + this.options.borderColor + ";"}),
				Builder.node("div", {className:"xb2", style: "background-color:" + this.options.backgroundColor + "; border-color:" + this.options.borderColor + ";"}),
				Builder.node("div", {className:"xb3", style: "background-color:" + this.options.backgroundColor + "; border-color:" + this.options.borderColor + ";"}),
				Builder.node("div", {className:"xb4", style: "background-color:" + this.options.backgroundColor + "; border-color:" + this.options.borderColor + ";"})
			]),
			Builder.node("div", {className: "xboxcontent", style: "background-color:" + this.options.backgroundColor + 
				"; border-color:" + this.options.borderColor + 
				((this.options.textColor != '') ? "; color:" + this.options.textColor : "") + 
				((this.options.textShadowColor != '') ? "; text-shadow:1px 1px 0" + this.options.textShadowColor + ";" : "")}).update(this.content), 
			Builder.node("div", {className:"xbottom"}, [
				Builder.node("div", {className:"xb4", style: "background-color:" + this.options.backgroundColor + "; border-color:" + this.options.borderColor + ";"}),
				Builder.node("div", {className:"xb3", style: "background-color:" + this.options.backgroundColor + "; border-color:" + this.options.borderColor + ";"}),
				Builder.node("div", {className:"xb2", style: "background-color:" + this.options.backgroundColor + "; border-color:" + this.options.borderColor + ";"}),
				Builder.node("div", {className:"xb1", style:"background-color:" + this.options.borderColor + ";"})
			]),
		]);
		document.body.insertBefore(this.tooltip, document.body.childNodes[0]);
		
		Element.extend(this.tooltip); // IE needs element to be manually extended
		this.options.width = this.tooltip.getWidth()+5;
		this.tooltip.style.width = this.options.width + 'px'; // IE7 needs width to be defined
		
		this.setup();
		
		if(this.options.mouseFollow)
			Event.observe(this.el, "mousemove", this.updateEvent);
			
		this.initialized = true;
		this.appearingFX = new Effect.Appear(this.tooltip, {duration: this.options.appearDuration, to: this.options.opacity });
	},
	setup: function(){
		// If content width is more then allowed max width, set width to max
		if(this.options.width > this.options.maxWidth) {
			this.options.width = this.options.maxWidth;
			this.tooltip.style.width = this.options.width + 'px';
		}
			
		// Tooltip doesn't fit the current document dimensions
		if(this.xCord + this.options.width >= Element.getWidth(document.body)) {
			this.options.align = "right";
			this.xCord = this.xCord - this.options.width + 20;
		}
		
		this.tooltip.style.left = this.xCord - 7 + "px";
		this.tooltip.style.top = this.yCord + 12 + "px";
	},
	_clearTimeout: function(timer) {
		clearTimeout(timer);
		clearInterval(timer);
		return null;
	}
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Version Number Selection
//////////////////////////////////////////////////////////////////////////////////////////////////////////

var VersionSimplifier =
{
	type: '',
	
	typeChanged: function(ev)
	{
		this.type = ev.element().value;	
		this.updateTextField();
	},

	pointNumberChanged: function(ev, num)
	{
		this.updateTextField();
	},
	
	updateTextField: function()
	{		
		var newValue = "", versionValue = "";
		
		for (var i = 1; i <= 7; i+=2)
		{
			if (i==7 && this.type)
				newValue = newValue + " " + this.type + " ";
				
			var val =  $('version' + i).value + $('version' + (i+1)).value;
			
			if (!val)
				continue;
			else
				newValue = newValue + ((i!=7||!this.type)&&i!=1&&newValue.length ? '.' : '') + val;
		}
		$('VersionField').update(newValue);
	}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Project Channel Editor
//////////////////////////////////////////////////////////////////////////////////////////////////////////

var CategorySelectionLimiter = 
{
	numSelected: 0,
	maxSelection: 3,
	
	limitSelection: function(el)
	{
		if (el.checked && (this.numSelected + 1 > this.maxSelection))
		{
			el.checked = '';
			new Effect.Pulsate('MaxSelectionLabel', {pulses:2, duration: .75});
			return;
		}
		
		this.numSelected += el.checked ? 1 : -1;
		return true;
	}
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Project Channel Editor
//////////////////////////////////////////////////////////////////////////////////////////////////////////

var UsernameAvailabilityTester = 
{
	usernameChanged: function(ev)
	{
		new Ajax.Updater({success: 'UsernameAvailabilityLabel'}, _BasePath + 'users/ajaxUserNameAvailable/',
	        {	asynchronous:true,
				onComplete:function(transport){					
					$('UsernameAvailabilityLabel').style.color = transport.responseText == 'Available' ? "#71B959" : "#99151A";
				}, 
	       		method:'post',
				parameters:{'username' : $('UsernameField').value }
			});
	}
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Alerts
//////////////////////////////////////////////////////////////////////////////////////////////////////////

var AlertManager = 
{
	deleteAlert: function(alertID)
	{
		
		new Ajax.Request(_BasePath + 'users/deleteAlert/' + alertID + "?ajax=1",
			{	method:'post',
				onComplete:function(transport) { 
					if (transport.responseText.indexOf('deleted') != 0)
						return;

					var alertBox = $$("div.main-box.dialog-box.type1").first(), alertContainer = $$('div.AlertContainer').first(), isLastAlert = true;
					
					if (alertContainer)
						alertContainer.childElements().each(function(el) {
							if ((el.id.indexOf("Alert") == 0) && (el.style.display != 'none') && (el.id != 'Alert' + alertID) )
								isLastAlert = false;
						});
																
					if (isLastAlert && alertBox)
						new Effect.SlideUp(alertBox, {duration: 0.5, queue: 'front'});
					else
						new Effect.SlideUp('Alert' + alertID, {duration: 0.3, queue: 'front'});						
				},
				parameters:{'delete' : 1}
			});
		
	}
	
	
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Input Throttling
//////////////////////////////////////////////////////////////////////////////////////////////////////////

function throttleInput(inputElement, counterElement, postfix)
{
	postfix = typeof(postfix) != 'undefined' ? postfix : "";
  
	new Form.Element.Observer(inputElement, .1,
		function(ev)
		{
			if ($(inputElement).value.length)
				$(counterElement).update($(inputElement).value.length + postfix);
			else 
				$(counterElement).update("");
		});
}


//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Inline URL verifier
//////////////////////////////////////////////////////////////////////////////////////////////////////////

var URLVerifier = 
{
	verifyURL: function(url)
	{
		new Ajax.Request(_BasePath + 'projects/ajaxUrlIsBinary',
	        {	asynchronous:true,
				onComplete:function(transport) {
					verifyURLFinished(transport.responseText == 'Passed');
				},
	       		method:'post',
				parameters:{'url' : url}
			});
	}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Tester registration cross-referencing
//////////////////////////////////////////////////////////////////////////////////////////////////////////

var TesterCrossReference = 
{
	haveWarnedAlready: false,
	nameFocusChanged: function()
	{
		TesterCrossReference.crossReferenceName($('firstName').value, $('lastName').value);
	},
	
	crossReferenceName: function(firstName, lastName)
	{
		if (this.haveWarnedAlready)
			return;
			
		new Ajax.Request(_BasePath + 'users/ajaxDeveloperExists',
	        {	asynchronous:false,
				onComplete:function(transport)
				{
					if (!this.haveWarnedAlready && transport.responseText == 'found')
					{
						this.haveWarnedAlready = true;
						startDialog(
							'<div class="dialog-content">We see that you\'re already registered as a Developer. We\'re happy to have you to register as a Beta Tester, but please be sure to keep in mind that since the programs on '+_SiteName+' are pre-release, you will be legally bound not to lift ideas from these applications. For more detailed information, please read our <a href="'+_BasePath+'terms" target="_NEW">Terms of Service</a> and the NDA agreement.<br/><br/>\
							Thanks and Enjoy!\
							</div><br/>\
							<button type="button" onclick="finishDialog();" class="dialog-submit">Continue Registration</button>');						
					}
				},
	       		method:'post',
				parameters: {'first': firstName, 'last': lastName}
			});
	}	
};



//////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Tester star ratings
//////////////////////////////////////////////////////////////////////////////////////////////////////////

var TesterRaters = [];
function TesterRater(initialRating, testerID)
{
	this.rating = initialRating;
	this.testerID = testerID;
	
	this.mouseOverStar = function(starNum, on)
	{
		if (on)
			this.updateStarOpacity(starNum);
		else
			this.updateStarOpacity();

	};
	this.updateStarOpacity = function(overrideRating)
	{
		
		displayedRating = overrideRating ? overrideRating : this.rating;

		for (var i = 1; i <= 5; i++)
		{
			var el = $('tester-rating-star-' + this.testerID + "-" + i);
			el.removeClassName("deselected-star-editor");
			if (i > displayedRating)
				el.addClassName("deselected-star-editor");
		}
	};
	
	this.rateTester = function(newRating)
	{	
		this.rating = newRating;
		
		var testerRatingEnclosure = $('tester-rating-enc-' + this.testerID);
		
		new Ajax.Request(_BasePath + 'users/rateTester/' + this.testerID,
	        {	asynchronous:true,
				onComplete:function(transport)
				{
						
				},
	       		method:'post',
				parameters: {'stars': this.rating}
			});
		
		return false;
	};
}
	
	
