/*************************************************************************************************
 * LENGTH_LIMIT_INCREMENT - amount to increment input maxlength upon "allowing more text"
 */
var LENGTH_LIMIT_INCREMENT = 400;

/*************************************************************************************************
 * MAX_LENGTH_LIMIT - the maximum limit on the input maxlength value
 */
var MAX_LENGTH_LIMIT = 1200;

/*************************************************************************************************
 * ocrUser - the user name if logged in
 */
var ocrUser;

/*************************************************************************************************
 * inputsToSave - all inputs that have unsaved changes
 */
var inputsToSave = [];

/*************************************************************************************************
 * savedLineIds - all the input ids for fields that have been saved in the editing session
 */
var savedLineIds = [];

/*************************************************************************************************
 * lastEnteredInput - maintain which was the last input field that was focused to allow refocus
 * 					  into the field after performing an action/toolbar function.
 */
var lastEnteredInput;


/*************************************************************************************************
 * EXISTING onClick HANDLERS
 */
function dc2(e){
	if (!e) e = window.event;
	var targ = (e.srcElement) ? e.srcElement : e.target ;
	jumpToLineOnMap(targ.id) ;
}

/*************************************************************************************************
 * updateStyleTimeout - only style the input and buttons once the user has stopped typing
 * 						improves performance in IE6
 */
var updateStyleTimeout;


/*************************************************************************************************
 * onOcrEditKeyup - handler for onKeyup event in all OCR text fields.
 * 
 * 
 */
function onOcrEditKeyup(e) {
	if (!e) e = window.event;
	var targ = (e.srcElement) ? e.srcElement : e.target;	

	var hasChanges = ocrTextHasChanges(targ.id);

	if (e.keyCode==13 || e.keyCode==38 || e.keyCode==40 || e.keyCode==9) { //return/enter or up or down	
 		var allInputs = $(".ocr-input .input");
		var currentIndex = $.inArray(targ, allInputs);
		if (e.keyCode==38) {
			if (currentIndex > 0) {
				allInputs[currentIndex-1].focus();
				allInputs[currentIndex-1].select();				
			}
		} else if (e.keyCode==9) {
			allInputs[currentIndex].focus();
			$(allInputs[currentIndex]).select();
		} else {
			if (currentIndex < allInputs.length - 1) {
				allInputs[currentIndex+1].focus();
				$(allInputs[currentIndex+1]).select();
			}			
		}
		return false;
	} else {
		storeCursorPosition(targ);
		if (hasTextReachedSizeLimit($(targ))) { //If user is logged in, allow extra text button
			if ( $(targ).val().length>$(targ).data("maxlength")) { //only truncate if required
				$(targ).val($(targ).val().substring(0, $(targ).data("maxlength")));
			}
			showLimitWarning(targ);
		} else {			
			hideLimitWarning(targ);
		}		
	}
	
	clearTimeout(updateStyleTimeout);
	updateStyleTimeout = setTimeout("styleInput('"+targ.id+"', "+hasChanges+");",250);
	
	
	return $(targ).data("allowKeyPress");
}


/*************************************************************************************************
 * showLimitWarning - displays warning when input field limit is reached
 * 		inputEl: Element - the input field to display the warning for 
 * 
 */
function showLimitWarning(inputEl) {
	if ($(inputEl).parent().find(".warning-message").length > 0) {
		return;
	}
	$(inputEl).after(
		"<div class='warning-message' style='display:none'>" +
			"<img src='/static/ndp/images/icon-error.png' alt='Warning - End of line reached'/> <b>End of line reached</b> "+
			((ocrUser!=null && ocrUser!="" && $(inputEl).data("maxlength")<MAX_LENGTH_LIMIT)?"<br/>Move to next line or <a href='javascript:void(0);' onclick='increaseSizeLimit(); return false;'>click to add missing text</a>. <a class='popup ocrhelp' href='/static/ndp/oxideDesign/ocrFix.html' title='Missing Text Help'><img src='/static/ndp/oxideDesign/img/template/icon-help.png' alt='Icon for Text Correction Help' /></a>":"")+
		"</div>"
	);
	$(inputEl).parent().find(".warning-message").show("normal");
	$(inputEl).parent().addClass("warning");
	$(".warning-message .ocrhelp").click(function() {ndp.openPopup(this);return false;});
}

/*************************************************************************************************
 * hideLimitWarning - hides the warning for when input field limit is reached
 * 		inputEl: Element - the input field to hide the warning for
 * 
 */
function hideLimitWarning(inputEl) {	
	setTimeout('$("#'+$(inputEl).attr("id")+'").parent().find(".warning-message").hide("normal", function() {$(this).parent().removeClass("warning");$(this).remove(); });', 500);
}


/*************************************************************************************************
 * styleInput - add CSS classes to the input and peripherals based on whether changes exist
 * 		inputEl: Element - the input to add styles to
 * 		hasChanges: Boolean - whether the input field contains any unsaved changes
 * 
 */
function styleInput(inputElId, hasChanges) {	
	var inputEl = $("#"+inputElId);
	if (hasChanges) {
		$(inputEl).parent().addClass("changed");
		$("#revertButton").removeClass("disabled");
		$(".ocrSaveButton").removeClass("disabled");
		
		$(".power-mode-toolbar .exit").css("display","none");
		$(".power-mode-toolbar .save-and-exit").css("display","inline");		
		
		if ($.inArray($(inputEl)[0], inputsToSave)<0) {
			inputsToSave.push($(inputEl)[0]);
		}
	} else if (!hasChanges) {
		$(inputEl).parent().removeClass("changed");
		$("#revertButton").addClass("disabled");
		if ($.inArray($(inputEl)[0], inputsToSave)>=0) {
			inputsToSave = $.grep(inputsToSave, function(value) {return value != $(inputEl)[0];}); 
		}
		if (inputsToSave.length==0) {
			$(".ocrSaveButton").addClass("disabled");
			$(".power-mode-toolbar .save-and-exit").css("display","none");
			$(".power-mode-toolbar .exit").css("display","inline");
		}
	}
	updateStyleTimeout = null;
}


/*************************************************************************************************
 * sanitiseText - replace all whitespace with "" or " "
 * 		aString: String - the string to "sanitize"
 * 
 */
function sanitiseText(aString) {
	return aString.replace(/^\s+/, "").replace(/\s+$/, "").replace(/\s\s+/g, " ");
}

/*************************************************************************************************
 * saveOCRchanges - save any outstanding changes by performing an ajax post containing all the 
 * 					changes expressed in an XML partial.  Upon success or failure, display messages
 * 					and style the text fields and toolbar buttons accordingly.
 * 
 */
function saveOCRchanges() {
	var changes = "";
	//var inputsToSave = linesRequiringSave;
	
	var linesWithNoChanges = [];
	
	if (inputsToSave.length>0) {
		
		for (var i=0; i<inputsToSave.length; i++) {
			//var targsel = "#" + inputsToSave[i].id.substring(3);

			var x = $(inputsToSave[i]).attr("x") ;
			var y = $(inputsToSave[i]).attr("y") ;
			
			// trim leading, trailing, multiple spaces			
			var originalContent = sanitiseText($(inputsToSave[i]).data("originalText"));		
			var updatedContent = sanitiseText($(inputsToSave[i]).val());
	
			//if (originalContent != updatedContent) {
				
				changes += "<line x='" + x + "' y='" + y + "'><originalContent>" + originalContent  +
					"</originalContent><updatedContent>" + updatedContent  + "</updatedContent></line>\n" ;
				//$(targsel).data("originalContent", originalContent);
			//} else {
			//	linesWithNoChanges.push(targsel);
			//}
		}
	}	
	
	if (changes.length<1) {
		return;
	}
	
	var dat = "simulatedMethod=put&articleId=" + articleId + "&articlePartId=" + articlePartId +
		"&changes=" + changes ; // &escape(changes) ;
		
	var postRes = "" ;
	
	$.ajax({
		type: "POST",
		url: "/ndp/del/correction",
		async: true,
		data: { simulatedMethod: "put", articleId: articleId, articlePartId: articlePartId,
			changes: changes},
		success: function(msg){			
			var postRes = msg ;			
			if (postRes.indexOf("<ok") >= 0) {
				if (!exitOnSave) {
					$.each(
						inputsToSave,
						function() {							
							$("#"+$(this).attr("id").substring(1)).removeClass("changed") ;
							$("#"+$(this).attr("id").substring(1)).addClass("corrected") ;
							$("#"+$(this).attr("id").substring(3)).addClass("corrected");														
							$("#"+$(this).attr("id").substring(1)).removeClass("saving");
							$("#"+$(this).attr("id")).data("originalText", $("#"+$(this).attr("id")).val());
							savedLineIds.push($(this).attr("id").substring(3));							
						}
					);
					
					inputsToSave = [];
					
					savedLineIds = $.unique(savedLineIds);
					
					$(".ocr").removeClass("saving");						
					$(".power-mode-toolbar a.save-and-exit, .power-mode-toolbar a.exit, .power-mode-toolbar a.cancel, .power-mode-toolbar a.insert-char").removeClass("disabled");					
					$(".power-mode-busy, .ocr-text .blockout").remove();
					
					$(".power-mode-toolbar a.save-and-exit").css("display","none");
					$(".power-mode-toolbar a.exit").css("display","inline");
					
					flashSuccessMessage();
				} else {						
					$(".ocr").removeClass("saving");
					$(".power-mode-busy, .ocr-text .blockout").remove();
					
					$.each(						
						inputsToSave,
						function() {
							savedLineIds.push(this.id.substring(3));							
						}
					);	
					
					savedLineIds = $.unique(savedLineIds);
					
					exitPowerMode();
				}
			} else {	
				$.each(
					inputsToSave,
					function() {
						//$(this).find(".input").removeAttr("disabled");
						$("#"+$(this).attr("id").substring(1)).removeClass("changed") ;
						$("#"+$(this).attr("id").substring(1)).removeClass("saving");
						$("#"+$(this).attr("id").substring(1)).removeClass("corrected") ;
						$("#"+$(this).attr("id").substring(1)).addClass("error") ;
					}
				);
				inputsToSave = [];
				$(".power-mode-busy, .ocr-text .blockout").remove();				
				$(".ocr").removeClass("saving");
				alert("Your corrections could not be saved.  Here's the system error:\n" +	msg) ;
			}
		},
		error: function(reqObj, msg, exceptionObj){
			$.each(
				inputsToSave,
				function() {					
					//$(this).find(".input").removeAttr("disabled");
					$("#"+$(this).attr("id").substring(1)).removeClass("saving") ;
					$("#"+$(this).attr("id").substring(1)).removeClass("corrected") ;
					$("#"+$(this).attr("id").substring(1)).addClass("error") ;
				}
			);
			// //KF - dont do this, which discards information about updates - 02sep09: inputsToSave = [];
			$(".power-mode-busy, .ocr-text .blockout").remove();
			$(".ocr").removeClass("saving");
			$(".power-mode-buttons.buttons a, .power-mode-toolbar a").removeClass("disabled"); // KF02sep09 - reinstate saving buttons!


			var postRes = "ERROR: " +  reqObj.statusText ;
			alert("Your corrections could not be saved.  Here's the system error:\n" +
				postRes + ", msg="+msg + ",exceptionObj="+exceptionObj) ;
		}
	});
	
	for (var i=0; i<inputsToSave.length; i++) {
		var efldId = "#ef" + inputsToSave[i].id.substring(3) ;
		$(efldId).removeClass("corrected");	
		$(efldId).addClass("saving") ;
	}
}


/*************************************************************************************************
 * ocrTextHasChanges - check if the input field has any outstanding changes i.e. is different from
 * 					   the original text.
 * 		inputFldId: String - the id for the input field
 * 
 */
function ocrTextHasChanges(inputFldId) {
	var originalContent = sanitiseText($('#' + inputFldId).data("originalText"));		
	var updatedContent = sanitiseText($('#' + inputFldId).val());
	return originalContent != updatedContent;
}


/*************************************************************************************************
 * syncWithPicture - sync the article image and current line (based on the coordinates x/y) with 
 * 					 the target input field.
 * 
 */
function syncWithPicture(targ,x,y) {
	if (x==null) x = $(targ).attr("x");
	if (y==null) y = $(targ).attr("y");
	var xx = {'x':x,'y':y,'width':$(targ).attr("ww"),'height':$(targ).attr("wh"),'bgcolour': '#88ff88', styleClass: 'highlightOpacity highlightLine'};
	$("#viewersurface .highlightLine").remove();
	ocrHighlightDiv  = viewerBean.addHighlight('hll_' + targ.id, xx, viewerBean.levels[viewerBean.zoomLevel], 
							viewerBean.levels[viewerBean.maxZoomLevel]) ;
	
	gotoAtTopLeft(x - 60, y - 80);
}


/*************************************************************************************************
 * jumpToLineOnMap - 
 * 
 */
function jumpToLineOnMap(targid) {
	var targsel = "#" + targid ;
	var targ = $(targsel) ;

	var x = $(targ).attr("x") ;
	if (x == null) return ;

	var y = $(targ).attr("y") ;

//	document.getElementById(spansBeenEditted[targid].inputFldId).focus() ;
//	gotoAtTopLeft((x - 60),y);
	// NN - add y buffer
	gotoAtTopLeft(x - 60, y - 80);
}


/*************************************************************************************************
 * showEAnno - 
 * 
 */
function showEAnno(i) {

	var anid = "#EAnno" + i ;
	$(anid).show() ;
}

/*************************************************************************************************
 * hideEAnno - 
 * 
 */
function hideEAnno(i) {

	var anid = "#EAnno" + i ;
	$(anid).hide() ;
}


/*************************************************************************************************
 * kp - the main onKeyUp handler for the OCR input text fields
 * 
 */
function kp(ev) {

	
	var myEvent = ev ? ev : window.event; 			// firefox : ie
	if (myEvent.keyCode == 123) {
		var s = myEvent.target || myEvent.srcElement ;	// firefox : ie

		var res = getSelectionRange(s) ;
	//	alert("pf12 " + s.value + " start=" + res.start + " end=" + res.end) ;
		var v = s.value ;
		// find first blank after us
		var i = v.indexOf(' ', res.start) ;
		if (i < 0) i = -1 ;
		var j = v.indexOf(' ', i+2) ;
		if (j < 0) j = v.length ;
		setSelectionRange(s, i+1, j) ;

		myEvent.cancelBubble = true ;
	} else {
		//var retVal = onOcrEditKeyup(myEvent);
		//console(retVal);
		return onOcrEditKeyup(myEvent);
	}
	return false;
}

/*function console(text) {
	$("#console").val(text+"\n"+$("#console").val());
}*/

/*************************************************************************************************
 * allowTextareaKeyPress - the onKeyPress handler for the OCR input text fields. Determines if 
 * 						   a keypress is allowed based on whether the limit has been reached.
 * 
 */
function allowTextareaKeyPress(ev){
	var myEvent = ev ? ev : window.event; 			// firefox : ie
	var targ = myEvent.target || myEvent.srcElement ;	// firefox : ie
	
	//Get the code of key pressed  
	var keyCode = myEvent.keyCode;
	
	//Check if it has a selected text  	
	var hasSelection = $(targ).getSelection().length>0;
	
	if (keyCode==13) { //clear all selections to avoid return deleting text
		if ($.browser.msie && hasSelection) { //ie
			document.selection.empty()
		} else if (!$.browser.msie && hasSelection){ //firefox
			window.getSelection().removeAllRanges();			
		}
		return false;
	}
	
	//return false if can't write more  
	return !(hasTextReachedSizeLimit($(targ)) && isKeyAllowedWhenLimitReached(myEvent) && !hasSelection);  
}

/*************************************************************************************************
 * isKeyAllowedWhenLimitReached - returns whether the keypress is allowed if the limit has been
 * 								  reached - e.g. A-Z disallowed, but CTRL-A allowed.
 * 
 */
function isKeyAllowedWhenLimitReached(myEvent) {
	return (myEvent.keyCode > 50 || myEvent.keyCode == 32 || myEvent.keyCode == 0 || myEvent.keyCode == 13) && !myEvent.ctrlKey && !myEvent.metaKey && !myEvent.altKey
}



/*
  This work is licensed under Creative Commons GNU GPL License
  http://creativecommons.org/licenses/GPL/2.0/
  Copyright (C) 2006 Russel Lindsay
  www.weetbixthecat.com
  version 0.5 (no TEXTAREA support, so it's only half complete)
*/


/**
  sets the index of the cursor and optionally selects text inside a text input
  element must be a reference to an INPUT (textarea not yet supported)
  if end omitted then cursor is positioned but no text is selected
*/
function setSelectionRange(element, start, end)
{
  if(end === undefined) end = start;
  
  // firefox
  if("selectionStart" in element)
  {
    element.setSelectionRange(start, end);
    element.focus(); // to make behaviour consistent with IE
  }
  // ie win
  else if(document.selection)
  {
    var range = element.createTextRange();
    range.collapse(true);
    range.moveStart("character", start);
    range.moveEnd("character", end - start);
    range.select();
  }
}

/**
  calculates the index of the cursor inside a text input
  element must be a reference to an INPUT (textarea not yet supported)
  returns a simple object {start:<int>, end:<int>} where <int> is -1 if cursor 
  is not in input field or functionality is not supported
*/
function getSelectionRange(element)
{
  var result = {start:-1, end:-1};
  // firefox
  if("selectionStart" in element)
    result = {start: element.selectionStart, end: element.selectionEnd};
  // ie win
  else if(document.selection)
  {
    // inputs only
    var range = document.selection.createRange();
    if(range.parentElement() == element)
    {
      var rangeS = range.duplicate();
      rangeS.moveEnd("textedit", 1);
      var rangeE = range.duplicate();
      rangeE.moveStart("textedit", -1);
      result = {start: element.value.length - rangeS.text.length, end: rangeE.text.length};
    }
  }
  
  return result;
}


/*************************************************************************************************
 * ocrMsgCount - counter used to ensure ocr messages have a unique id attribute (allows individual 
 * 				 selection of these fields).
 * 
 */
var ocrMsgCount = 0;


/*************************************************************************************************
 * flashOCRMessage - fade in/out a custom message within the context of the target input field.
 * 		targetEl: Element - the target input field
 * 		msg: String - the message to display
 * 		cssClass: String - the css class to apply to the message container element
 * 
 */
function flashOCRMessage(targetEl, msg, cssClass) {
	ocrMsgCount = ocrMsgCount + 1;
	var msgHtml = "<div id='ocrMsgBox" + ocrMsgCount + "' class='ocr-message-box";
	if (cssClass) {
		msgHtml += " "+cssClass;
	}
	msgHtml += "'>";
	msgHtml += msg;
	msgHtml += "</div>";
	
	
	$(targetEl).append(msgHtml)
	
	$("#ocrMsgBox"+ocrMsgCount).fadeIn();
	setTimeout('$("#ocrMsgBox'+ocrMsgCount+'").fadeOut("normal", function() {$(this).remove();});', 2500);
}


/*************************************************************************************************
 * storeCursorPosition - store the current position of the cursor in the passed input field
 * 		inputEl: Element - the input field where the cursor is currently positioned
 * 
 */
function storeCursorPosition(inputEl) {
	$(inputEl).data("selection", $(inputEl).getSelection());
	lastEnteredInput = $(inputEl);
}

/*************************************************************************************************
 * insertSpecialCharacter - insert the passed char into the last focused text field where the 
 * 							cursor was previously positioned.
 * 		event: Event
 * 		char: String - the character to insert into the text field
 * 
 */
function insertSpecialCharacter(event, char) {
	if (!lastEnteredInput) {return};
	var myEvent = event ? event : window.event;	
	var input = lastEnteredInput;
	if (hasTextReachedSizeLimit($(input))) {
		showLimitWarning($(input));
		return false;
	}
	var prevCursorLocation = input.val().length;
	if (input.data("selection")) {
		prevCursorLocation = input.data("selection").start;
		input.attr("value", input.val().substring(0, prevCursorLocation) + char + input.val().substring(prevCursorLocation));
		setCursor($(input)[0],prevCursorLocation+1,prevCursorLocation+1);
	} else {
		input.attr("value", input.val() + char);
		$(input).focus();
	}
	styleInput($(input).attr("id"), ocrTextHasChanges($(input).attr("id")));
	//$(input).parent().addClass("changed");	
}


/*************************************************************************************************
 * characterMenuHtml - the HTML for the Insert Symbol menu
 * 
 */
function characterMenuHtml() {
	return  "<ul id='charMenu' class='contextMenu buttons'>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00A3\")'>\u00A3&nbsp;Pound</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00C6\")'>\u00C6&nbsp;Ligature AE</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00E6\")'>\u00E6&nbsp;Ligature ae</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00B0\")'>\u00B0&nbsp;Degree</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u2014\")'>\u2014&nbsp;Em Dash</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00B6\")'>\u00B6&nbsp;Pilcrow</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00A7\")'>\u00A7&nbsp;Section</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00BC\")'>\u00BC&nbsp;One Quarter</a></li>" +
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00BD\")'>\u00BD&nbsp;One Half</a></li>" +			
			"	<li><a href='javascript:void()' onclick='insertSpecialCharacter(event, \"\u00BE\")'>\u00BE&nbsp;Three Quarters</a></li>" +
			"</ul>";
}


/*************************************************************************************************
 * hasTextReachedSizeLimit - determine if the passed input field has reached its maxlength limit
 * 
 */
function hasTextReachedSizeLimit(inputEl) {
	if ($(inputEl).val().length>=$(inputEl).data("maxlength")) {		
		return true;
	} else {
		return false;
	};
}


/*************************************************************************************************
 * increaseSizeLimit - increase the maxlength of the passed input field based on the constants
 * 					   LENGTH_LIMIT_INCREMENT and MAX_LENGTH_LIMIT.
 * 
 */
function increaseSizeLimit() {
	var inputEl = lastEnteredInput;
	$(inputEl).data("maxlength", Math.min($(inputEl).data("maxlength") + LENGTH_LIMIT_INCREMENT, MAX_LENGTH_LIMIT));
	$(inputEl)[0].focus();
	flashOCRMessage($(inputEl).parent(), "Limit Increased", "warning");
}


/*************************************************************************************************
 * confirmExit - if leaving the page, display a message to prompt user if outstanding changes exist
 * 
 */
function confirmExit() {
  if (inputsToSave.length>0) {	 
	  return "You have attempted to leave this page.\n\nIf you have made any changes without clicking the Save button, your changes will be lost.\n\nAre you sure you want to exit this page?";
  }
}


/*************************************************************************************************
 * enterPowerEdit - enter the edit mode for the current article page.
 * 		editLineId: String - if user entered via the line-hover "fix this text" then focus that line
 * 							 upon entering the edit mode.
 * 
 */
function enterPowerEdit(editLineId) {
	ocrUser = $.cookie('newspaperUser');
	ndp.enterOCRFullScreen();
	
	window.onbeforeunload = confirmExit;
	
	$(".ocr").addClass("power-mode");

	$("#column").after("<img src='/static/ndp/images/busy_f0f0f0.gif' class='power-mode-busy' style='z-index: 1111; position: absolute; top: 40%; left: "+$("#column").width()/2+"px;' />");
	
	//** Add big random number to ensure page is retrieved from server and not cache!  IE7 bug.
	$(".ocr .ocr-text").load("/ndp/del/articleForEdit/"+articleId+((pageId!=null)?"/"+pageId:"")+"?"+Math.floor(Math.random()*110000000000), null, function() {
		/*$.each($(".ocr-input textarea"), function() {
			$(this).autogrow();
			$(this).data("originalText", $(this).val());
		});*/
		
		if (editLineId) {
			setTimeout("$('#ef"+editLineId+" .input')[0].focus();",0);		
			setTimeout("$('#ef"+editLineId+" .input').select();",0);
		} else {
			setTimeout("$('.ocr-text .input')[0].focus();",0);
			setTimeout("$('.ocr-text .input:first').select();",0);
		}	
		$(".power-mode-busy").remove();
	});
	$("#column").before(
			
			'<div class="power-mode-toolbar-container">'+
			'<div class="power-mode-toolbar">' +			
			'	<h4>'+			
			'		Electronically Translated Text'+		
			'	</h4>'+
			'	<div class="ocrhelp-container">'+
			'		<a class="popup ocrhelp" href="/static/ndp/oxideDesign/ocrFix.html" title="Text Correction Help">Need help?</a> <a class="popup ocrhelp" href="/static/ndp/oxideDesign/ocrFix.html" title="Text Correction Help"><img src="/static/ndp/oxideDesign/img/template/icon-help.png" alt="Icon for Text Correction Help" /></a>' +
			'		<a class="popup ocrhelp keyboard-shortcuts" href="/static/ndp/oxideDesign/ocrFix.html" title="Keyboard Shortcuts">Keyboard Shortcuts</a> <a class="popup ocrhelp" href="/static/ndp/oxideDesign/ocrFix.html" title="Keyboard Shortcuts"><img src="/static/ndp/oxideDesign/img/template/icon-keyboard.png" alt="Icon for Keyboard Shortcuts" /></a>' +
			'	</div>'+	
			'	<div class="buttons primary-actions left">'+
			'		<a accesskey="s" class="ocrSaveButton save disabled" href="javascript:void(0);" title="Save all changes and continue editing" onclick="if (!$(this).hasClass(\'disabled\')) {powerModeSave(); return false;}; return false;">Save</a>' +
			'		<a accesskey="e" class="exit" title="Exit editing and return to the article view" href="javascript:void(0);" onclick="exitPowerMode(); return false;">Exit</a>' +
			'		<a accesskey="e" style="display:none" class="save-and-exit" title="Save all changes and return to the article view" href="javascript:void(0);" onclick="powerModeSaveAndExit(); return false;">Save &amp; Exit</a>' +
			'		<a accesskey="x" class="cancel" title="Discard all changes and return to the article view" href="javascript:void(0);" onclick="exitPowerMode(); return false;">Cancel</a>' +
			'	</div>'+
			'	<div class="actions-seperator"></div>'+
			'	<div class="buttons secondary-actions left">'+
			'		<a id="revertButton" class="revert disabled" href="javascript:void(0);" onclick="if (!$(this).hasClass(\'disabled\')) {revertChanges(this);};  return false;" title="Undo all changes made to this line">Undo Line</a>' +
			' 		<a id="charButton" class="insert-char" href="javascript:void(0);" title="Insert special character">Insert Symbol</a>' +
			'	</div>'+
			'	<div class="clear-fix"></div>'+
			'</div>'+
			characterMenuHtml() +	
			'</div>'
			
	);	
	
	$('#charButton').contextMenu({menu: 'charMenu', bind: 'click'});

	$(".power-mode-toolbar .ocrhelp").click(function() {ndp.openPopup(this);return false;});
	
}

/*************************************************************************************************
 * exitPowerMode - replace the edit mode text fields with the original article translated text view
 * 
 */
function exitPowerMode() {
	
	window.onbeforeunload = null;
	
	inputsToSave = [];
	$(".power-mode-buttons, .power-mode-toolbar-container, .autogrow-zone, .ocr-info-message").remove();
	
	$(".ocr").addClass("exiting-edit");
	
	ndp.exitOCRFullScreen();
	
	$(".ocr-text").append("<img src='/static/ndp/images/busy_f0f0f0.gif' class='power-mode-busy' style='z-index: 1111; position: absolute; top: 25%; left: "+$("#column").width()/2+"px;' />");
	
	//** Add big random number to ensure page is retrieved from server and not cache!  IE7 bug.
	$(".ocr .ocr-text").load("/ndp/del/articleForView/"+articleId+((pageId!=null)?"/"+pageId:"")+"?"+Math.floor(Math.random()*110000000000)+((searchTerm!=null||searchTerm!="")?"&searchTerm="+searchTerm:""), null, function() {
		$(".ocr").removeClass("power-mode").removeClass("exiting-edit");
		$("#viewersurface .highlightLine").remove();
		//$(".power-mode-busy").remove();
		if (exitOnSave) {
			flashSuccessMessageAfterExit();
		} else {
			$.each(
				savedLineIds,
				function() {
					$("#"+this).addClass("corrected");						
				}
			);
		}
		if (pageId!=null && pageId!="") {
			document.location.hash = "pstart"+pageId;
		}
		exitOnSave = false;
	});		
}

/*************************************************************************************************
 * exitOnSave - whether or not changes should be saved upon exiting edit mode ("Exit and Save" button)
 */
var exitOnSave = false;

/*************************************************************************************************
 * powerModeSave - perform a save for all outstanding line changes.
 *  
 */
function powerModeSave() {
	clearTimeout(updateStyleTimeout);
	if ($(".ocr").hasClass("saving")) { //in case of double click
		return;
	}
	$(".power-mode-buttons.buttons a, .power-mode-toolbar a").addClass("disabled");		
	$("#column").after("<img src='/static/ndp/images/busy_f0f0f0.gif' class='power-mode-busy' style='z-index: 1111; position: absolute; top: 40%; left: "+$("#column").width()/2+"px;' />");
	/*$.each(
		$('.ocr-input input'),
		function() {
			$(this).attr("disabled","true");
		}	
	);*/
	$(".ocr").addClass("saving");
	$(".ocr-text").append("<div class='blockout'></div>");
	$(".ocr-text .blockout").css({
		height: $(".ocr-text").height()+"px"		
	});
	saveOCRchanges();
	
}


/*************************************************************************************************
 * powerModeSaveAndExit - perform a save for all outstanding changes then exit edit mode
 *  
 */
function powerModeSaveAndExit() {
	if ($(".ocr-input.changed:first").length>0) {
		exitOnSave = true;
		powerModeSave();
	} else {
		exitPowerMode();
	}
}


/*************************************************************************************************
 * flashSuccessMessage - display a success message in context with the input fields that have been 
 * 						 saved
 *  
 */
function flashSuccessMessage() {
	$.each(
		$(".ocr-input.corrected"),
		function() {
			flashOCRMessage(this, "Saved", "success")
		}
	);
}


/*************************************************************************************************
 * flashSuccessMessageAfterExit - display a success message in context with the article lines that 
 * 								  have been saved
 *  
 */
function flashSuccessMessageAfterExit() {
	$.each(
		savedLineIds,
		function() {
			$("#"+this).removeClass("changed").addClass("corrected");
			flashOCRMessage($("#"+this), "Saved", "success");			
		}
	);
	savedLineIds = [];
}


/*************************************************************************************************
 * revertChanges - revert the last focused text field to its original text
 * 		buttonEl: Element - the "Undo Line" button
 *  
 */
function revertChanges(buttonEl) {
	clearTimeout(updateStyleTimeout);
	$(lastEnteredInput).val($(lastEnteredInput).data("originalText"));
	$(lastEnteredInput).parent().removeClass("changed");
	$(buttonEl).addClass("disabled");
	if ($(".ocr-input.changed").length==0) {
		$(".ocrSaveButton").addClass("disabled");
		$(".power-mode-toolbar .save-and-exit").css("display","none");
		$(".power-mode-toolbar .exit").css("display","inline");
	}
	refreshTextAreaSize($(lastEnteredInput)[0]);
	hideLimitWarning($(lastEnteredInput));
}

/*************************************************************************************************
 * ocrInputFocused - the onFocus handler for all OCR text input fields. 
 * 		inputEl: Element - the text field being focused.
 *  
 */
function ocrInputFocused(inputEl) {
	if ($(inputEl).hasClass("fresh")) {
		$(inputEl).autogrow();
		//$(inputEl).val($.trim($(inputEl).val()));
		$(inputEl).data("originalText", $(inputEl).val());
		$(inputEl).removeClass("fresh");
		$(inputEl).data("maxlength",parseInt($(inputEl).val().length*1.1+10));
	}
	storeCursorPosition(inputEl);
	//lastEnteredInput = inputEl;
	$(inputEl).parent().addClass('focused');
	if ($(inputEl).parent().hasClass("changed")) {
		$("#revertButton").removeClass("disabled");
	} else {
		$("#revertButton").addClass("disabled");
	}
	
	if (hasTextReachedSizeLimit(inputEl)) {
		showLimitWarning(inputEl);
	}
	
	try {
		syncWithPicture($(inputEl)[0]);
	} catch(e) {
	};
}


/*************************************************************************************************
 * ocrInputBlurred - the onBlur handler for all OCR text input fields
 * 		inputEl: Element - the text field being blurred
 *  
 */
function ocrInputBlurred(inputEl) {
	$(inputEl).parent().removeClass('focused');
	if (inputEl.nodeName=="TEXTAREA") {
		$(inputEl).val(stripCarriageReturns($(inputEl).val()));
	}
	hideLimitWarning(inputEl);
}


/*************************************************************************************************
 * stripCarriageReturns - remove all carriage returns from the string argument
 * 		aString: String - the string to strip...
 *  
 */
function stripCarriageReturns(aString) {
	return aString.replace("\n","").replace("\r","");
}


/*************************************************************************************************
 * refreshTextAreaSize - refresh the dynamic textarea sizing if non keypress event changes the 
 * 						 input's content
 * 		textareaEl: Element - the input field to refresh
 *  
 */
function refreshTextAreaSize(textareaEl) {
	if ($(textareaEl).data("update")) {
		$(textareaEl).data("update").apply(textareaEl);
	}
}


/*************************************************************************************************
 * setCursor - position the cursor in the element at the st index (create a selection if the end 
 * 			   index is provided)
 *  	el: Element - the element to position the cursor in
 *  	st: int - start index 
 *  	end: int - end index
 */
function setCursor(el,st,end) { 
	if (el.setSelectionRange) { 
		el.focus(); 
		el.setSelectionRange(st,end); 
	} else { 
		if (el.createTextRange) { 
			range=el.createTextRange(); 
			range.collapse(true); 
			range.moveEnd('character',end); 
			range.moveStart('character',st); 
			range.select(); 
		} 
	}
	storeCursorPosition(el);
} 

