/* ======================================================================================================
  Event shortcuts
====================================================================================================== */
function Evt(evt) 
{
  evt = evt ? evt : window.event; 
	this.evt = evt; 
	this.source = evt.target ? evt.target : evt.srcElement;
	this.x = evt.pageX ? evt.pageX : evt.clientX;
	this.y = evt.pageY ? evt.pageY : evt.clientY;
	
	
	if (marvin.isNetscape)
	{
	  this.button = e.which;
	  /*
	  if (this.button == 0)
	   this.button = marvin.button_left;
	  */
	}
	else
	  this.button = evt.button;
	
	//this.docX = this.x + document.body.scrollLeft - document.body.clientLeft;
	//this.docY = this.y + document.body.scrollTop  - document.body.clientTop;
	//alert("ST:" + document.body.scrollTop);
	//alert("CT:"+document.body.clientTop);
}

Evt.prototype.toString = function () 
{
	return "Evt [ x = " + this.x + ", y = " + this.y + " ]";
};

Evt.prototype.consume = function () 
{
	if (this.evt.stopPropagation) 
	{
		this.evt.stopPropagation();
		this.evt.preventDefault();
	} 
	else if (this.evt.cancelBubble) 
	{
		this.evt.cancelBubble = true;
		this.evt.returnValue  = false;
	}
};

Evt.addEventListener = function (target,type,func,bubbles) 
{
	if (document.addEventListener) 
	{
		target.addEventListener(type,func,bubbles);
	} 
	else if (document.attachEvent) 
	{
		target.attachEvent("on"+type,func,bubbles);
	} 
	else 
	{
		target["on"+type] = func;
	}
};

Evt.removeEventListener = function (target,type,func,bubbles) 
{
	if (document.removeEventListener) 
	{
		target.removeEventListener(type,func,bubbles);
	} 
	else if (document.detachEvent) 
	{
		target.detachEvent("on"+type,func,bubbles);
	} 
	else 
	{
		target["on"+type] = null;
	}
};



/* ======================================================================================================
  Basic stuff
====================================================================================================== */
  // Use object as a namespace for various functions and variables
var marvin = {};

marvin.key_escape = 27;
marvin.key_enter = 13;
marvin.key_up = 38;
marvin.key_down = 40;
marvin.key_tab = 9;

marvin.button_left = 1;
marvin.button_right = 2;

marvin.isNetscape = (navigator.appName == "Netscape");


marvin.addEvent = function (obj, evType, fn)
{ 
  if (obj.addEventListener)
  { 
    obj.addEventListener(evType, fn, false); 
    return true; 
  } 
  else if (obj.attachEvent)
  { 
    var r = obj.attachEvent("on"+evType, fn); 
    return r; 
  } 
  else 
  { 
   return false; 
  } 
}


marvin.isDeletingChar = function(key)
{
  return key == 8 || key == 46;
}


/* ======================================================================================================
  Handling of checks for "data changed by user".
  Involves code to disable/enable various buttons depending on whether or not the user has changed
  any data in the form.
====================================================================================================== */

  // Indicate whether the data has been changed or not
marvin.dataChanged = false;

  // Registered event handlers for data changed events
marvin.dataChangedHandlers = [];


marvin.registerDataChangedHandler = function(handler, param)
{
  this.dataChangedHandlers[this.dataChangedHandlers.length] = { handler: handler, param: param };
}


  // Event handler that enables/disables the associated button
marvin.buttonDataChangedHandler = function(cmd, buttonId)
{
  var button = document.getElementById(buttonId);
  if (button != null)
  {
    if (cmd == "changed")
      button.disabled = false;
    if (cmd == "reset")
      button.disabled = true;
  }
}


  // Event handler that disables/enables the associated button
marvin.buttonDataChangedInvHandler = function(cmd, buttonId)
{
  var button = document.getElementById(buttonId);
  if (button != null)
  {
    if (cmd == "changed")
      button.disabled = true;
    if (cmd == "reset")
      button.disabled = false;
  }
}


marvin.dataChangedCheckInProgress = false;

  // Base code for calling event handlers when user changes data
marvin.handleDataChanged = function(element)
{
  if (this.dataChangedCheckInProgress)
    return;
  marvin.dataChangedCheckInProgress = true;

  if (element != null)
    marvin.handleMandatoryCheck(element);
  
    // Don't do anything if data is changed already
  if (this.dataChanged == true)
  {
    marvin.dataChangedCheckInProgress = false;
    return;
  }
    
  this.dataChanged = true;
  
  for (var i in this.dataChangedHandlers)
  {
    var handler = this.dataChangedHandlers[i];
    if( handler.handler != null )
      handler.handler("changed", handler.param);
  }
  
  marvin.dataChangedCheckInProgress = false;
}


marvin.handleMandatoryCheck = function(element)
{
  if (element.type == "text"  &&  element.className.indexOf("mandatory") >= 0)
  {
    if (element.value == "")
    {
      if (element.className.indexOf(" empty-mandatory") < 0)
      {
        if (element.className.indexOf("mandatory") >= 0)
          element.className = element.className.replace(/[ ]?mandatory/, "");
          
        element.className += " empty-mandatory";
      }
    }
    else
    {
      if (element.className.indexOf("empty-mandatory") >= 0)
        element.className = element.className.replace(/[ ]?empty-mandatory/, "");
        
      if (element.className.indexOf(" mandatory") < 0)
        element.className += " mandatory";
    }
  }
}


  // Base code for calling event handlers when user resets data
marvin.handleDataReset = function()
{
  this.dataChanged = false;
  
  for (var i in this.dataChangedHandlers)
  {
    var handler = this.dataChangedHandlers[i];
    if( handler.handler != null )
      handler.handler("reset", handler.param);
  }
}


  // Called when user clicks a "reset" button.
  // Checks for data changed by user - if changed then make sure user confirms click on reset button
marvin.handleOnClickReset = function(msg)
{
  if (this.dataChanged)
    if (!confirm(msg))
      return false;
  
  // Reset is confirmed - now make sure all event listeners gets to know it
  // Unfortunately some event handlers disable the reset button - and this 
  // also disables the reset functionality, thereby rendering the reset useless!
  // So wait until the reset has been performed, and then call the evnt handlers. Yuck!
  setTimeout("marvin.handleDataReset()", 500);
  
  return true;
}

/* ======================================================================================================
  Various JavaScript utilities
====================================================================================================== */

marvin.getWindowWidth = function()
{
  return marvin.getWindowDimensions()[0];
}

marvin.getWindowHeight = function()
{
  return marvin.getWindowDimensions()[1];
}

marvin.getWindowDimensions = function()
{
  var x,y;
  if (self.innerHeight) // all except Explorer
  {
	  x = self.innerWidth;
	  y = self.innerHeight;
  }
  else if (document.documentElement && document.documentElement.clientHeight)
	  // Explorer 6 Strict Mode
  {
	  x = document.documentElement.clientWidth;
	  y = document.documentElement.clientHeight;
  }
  else if (document.body) // other Explorers
  {
	  x = document.body.clientWidth;
	  y = document.body.clientHeight;
  }
  
  return [x, y];
}

marvin.getWindowCoords = function(width, height)
{
  var screenW = 800, screenH = 600;

  if (screen.availWidth  &&  screen.availHeight)
  {
    screenW = screen.availWidth;
    screenH = screen.availHeight;
  }
  
  var leftPos = (screenW-width)/2;
  var topPos = (screenH-height)/2;
  
  return "top=" + topPos + "px,screenY=" + topPos + "px,left=" + leftPos + "px,screenX=" + leftPos
         + "px,height=" + height + "px,width=" + width +"px";
}


marvin.getWindowCoordsScreenSized = function(screenPercentageW, screenPercentageH)
{
  var screenW = 800, screenH = 600;

  if (screen.availWidth  &&  screen.availHeight)
  {
    screenW = screen.availWidth;
    screenH = screen.availHeight;
  }
  
  var width = screenW * screenPercentageW / 100;
  var height = screenH * screenPercentageH / 100;
  
  return getWindowCoords(width,height);
}


marvin.openWindowInCenter = function(url, windowName, width, height, otherInfo)
{
  if (otherInfo != null  &&  otherInfo[0] != ',')
    otherInfo = ','+otherInfo;
  return window.open(url, windowName, marvin.getWindowCoords(width,height)+",status=1"+otherInfo);
}


marvin.openWindowScreenSized = function(url, windowName, screenPercentageW, screenPercentageH, otherInfo)
{
  if (otherInfo != null  &&  otherInfo[0] != ',')
    otherInfo = ','+otherInfo;
  return window.open(url, windowName, marvin.getWindowCoordsScreenSized(screenPercentageW,screenPercentageH)+",status=1"+otherInfo);
}


marvin.disableActivateButton = false;


marvin.ActivateButton = function(buttonId, evt)
{
  var btn = document.getElementById(buttonId);
  if (typeof btn != "undefined")
  {
    var submit = false;
    if (document.all && evt.keyCode == 13)
      submit = true;
    else if (evt.which == 13)
      submit = true;
      
    if (submit)
    {
      evt.returnValue = false;
      evt.cancel = true;
      evt.cancelBubble = true;

      if (evt.preventDefault)
        evt.preventDefault();
      
      if(evt.stopPropagation)
        evt.stopPropagation();
    
      
      // Make it possible for other event handlers to (one-shot) disable this feature
      if (marvin.disableActivateButton)
      {
        marvin.disableActivateButton = false;
      }
      else
      {      
        marvin.disableActivateButton = false;
        btn.click();
      }
    }
  }
}

marvin.NotEnterPressed = function(evt)
{
  if ( evt.keyCode == 13 )
  {
    return false;
  }
  else
  {
    return true;
  }
}

marvin.getElementsByClass = function(searchClass,node,tag) {
	var classElements = new Array();
	if ( node == null )
		node = document;
	if ( tag == null )
		tag = '*';
	var els = node.getElementsByTagName(tag);
	var elsLen = els.length;
	//var pattern = new RegExp("(^|.*\s|\s)"+searchClass+"(\s|\s.*|$)");
	var pattern = new RegExp('/b^|' + searchClass + '|$/b');
	//var pattern = new RegExp("/"+searchClass+"/");
	for (i = 0, j = 0; i < elsLen; i++) {
		if ( pattern.test(els[i].className) ) {
			classElements[j] = els[i];
			j++;
		}
	}
	return classElements;
}

marvin.getCursorPosition = function(e) {
  e = e || window.event;
  var cursor = {x:0, y:0};
  if (e.pageX || e.pageY) {
      cursor.x = e.pageX;
      cursor.y = e.pageY;
  } 
  else {
      var de = document.documentElement;
      var b = document.body;
      cursor.x = e.clientX + 
          (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0);
      cursor.y = e.clientY + 
          (de.scrollTop || b.scrollTop) - (de.clientTop || 0);
  }
  return cursor;
}


/* ======================================================================================================
  Utilities for searching
====================================================================================================== */

marvin.openSearchWindow = function(func, destinationId, query)
{
  marvin.openWindowInCenter("search.aspx?searchtype=field&func="+func+"&destinationId="+destinationId+"&"+query,
                            "", 600, 600, "resizable=1,scrollbars=1");
}


marvin.searchCancel = function()
{
  window.opener.focus();
  window.close();
}

/* ======================================================================================================
  Div toggleling helpers
====================================================================================================== */

marvin.div = {};

marvin.div.show = function(id)
{
  var div = document.getElementById(id);
  div.style.display = 'block';
}

/*
marvin.div.showDropDown = function(id, speed, maxheight)
{
  var div = document.getElementById(id);
  if ( div.style.height < maxheight )
    div.style.height = div.style.height + 
}
*/

marvin.div.hide = function(id)
{
  var div = document.getElementById(id);
  div.style.display = 'none';
}

marvin.div.toggle = function(id)
{
  var div = document.getElementById(id);
  
  if ( div.style.display == 'none' )
    marvin.div.show(id);
  else
    marvin.div.hide(id);
}

/* ======================================================================================================
  Popup helpers
====================================================================================================== */

marvin.popup = {};

marvin.popup.findPosition = function ( oLink ) 
{
  var startLink = oLink;
  var posX;
  var posY;
  
  if( oLink.offsetParent ) {
    for( posX = 0, posY = 0; oLink.offsetParent; oLink = oLink.offsetParent ) {
      posX += oLink.offsetLeft - oLink.scrollLeft;
      posY += oLink.offsetTop - oLink.scrollTop;
    }
    
    oLink = startLink;
    while (oLink.parentNode)
    {
      oLink = oLink.parentNode;
      if (oLink.scrollLeft && oLink.scrollTop)
      {
        posX -= oLink.scrollLeft;
        posY -= oLink.scrollTop;
      }
    }
    
    return [ posX, posY ];
  } else {
    return [ oLink.x, oLink.y];
  }
}

marvin.popup.showInPlace = function(popupDiv, parentElement, offsetX, offsetY)
{
  var pos = marvin.popup.findPosition(parentElement);

/*  
  var agt = navigator.userAgent.toLowerCase();
  var is_ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
  if ( is_ie )
    offsetY = offsetY;
*/
  marvin.popup.showInPosition(popupDiv, pos[0], pos[1], offsetX, offsetY);
}
  
marvin.popup.showInPosition = function(popupDiv, x, y, offsetX, offsetY)
{
  popupDiv.style.left = (x + offsetX) + 'px';
  popupDiv.style.top = (y + offsetY) + 'px';
  popupDiv.style.position = 'absolute';
  
  marvin.popup.show(popupDiv);
}


marvin.popup.show = function(popupDiv)
{
  popupDiv.style.visibility = 'visible';
  popupDiv.style.display = 'block';
}


marvin.popup.hideId = function(popupDivId)
{
  var popupDiv = document.getElementById(popupDivId);
  marvin.popup.hide(popupDiv);
}


marvin.popup.hide = function(popupDiv)
{
  popupDiv.style.visibility = 'hidden';
}


marvin.popup.toggleInPlaceId = function(popupDivId, parentElementId, offsetX, offsetY)
{
  var parentElement = document.getElementById(parentElementId);
  var popupDiv = document.getElementById(popupDivId);
  
  if ( popupDiv.style.visibility == 'hidden' )
    marvin.popup.showInPlace(popupDiv, parentElement, offsetX, offsetY);
  else
    marvin.popup.hide(popupDiv);
}


/* ======================================================================================================
  Autocomplete
====================================================================================================== */

marvin.autocomplete = {};

// How many lines in auto complete list
marvin.autocomplete.lineCount = 0;

// Current selected line in auto complete list
marvin.autocomplete.selectedLineNo = 0;

// Location of the values you can select
marvin.autocomplete.values = [];

marvin.autocomplete.titles = [];

// Reference to text input with auto complete
marvin.autocomplete.inputElement = null;

marvin.autocomplete.inputTitlesElement = null;

// Reference to suggestion div element (list of options)
marvin.autocomplete.suggestionDiv = null;

marvin.autocomplete.suggestionDivIFrame = null;

marvin.autocomplete.timeoutReference = null;

marvin.autocomplete.previousText = null;

marvin.autocomplete.typeAhead = function(input, text)
{
  if (input.value != text)
  {
    if (input.createTextRange || input.setSelectionRange)
    {
      var len = input.value.length; 
      input.value = text; 
      marvin.autocomplete.selectRange(input, len, text.length);
    }
  }
}


marvin.autocomplete.selectRange = function(input, start, len)
{
  //use text ranges for Internet Explorer
  if (input.createTextRange) 
  {
    var oRange = input.createTextRange(); 
    oRange.moveStart("character", start); 
    oRange.moveEnd("character", len - input.value.length);      
    oRange.select();
  } 
  //use setSelectionRange() for Mozilla
  else if (input.setSelectionRange) 
  {
    input.setSelectionRange(start, len);
  }     

  //set focus back to the input
  input.focus();
}

marvin.autocomplete.ajax_toggle = function(ajax, inputId, titlesInputId, paramInputId, evt)
{
  var suggestionDiv = document.getElementById("marvinSuggestionDiv");
  if ( suggestionDiv.style.visibility == 'visible' )
  {
    marvin.autocomplete.cancelPopup();
    return false;
  }  
  else return marvin.autocomplete.ajax_update(ajax, inputId, titlesInputId, paramInputId, evt);
    
}

// This is the function to call when requesting an Ajax call.
marvin.autocomplete.ajax_update = function(ajax, inputId, titlesInputId, paramInputId, evt)
{
  var key = (document.all ? evt.keyCode : evt.which);
  if (key == marvin.key_tab) // Ignore when getting focus via tab
    return;
  var forceSuggestions = false;

  if (marvin.autocomplete.inputElement != null)
  {
    if (key == marvin.key_up)
    {
      this.moveSelectedLineUp();
      return false;
    }
    if (key == marvin.key_down)
    {
      this.moveSelectedLineDown();
      return false;
    }
    if (key == marvin.key_enter)
    {
    
      marvin.autocomplete.selectItem();
      marvin.autocomplete.cancelPopup();
      return false;
    }
  }
  else
  {
    if (key == marvin.key_down || evt.type == 'click')
    {
      forceSuggestions = true;
    }
  }

  // Note: try to avoid modifying element here. This starts of various "onchange" handlers.
  
  var element = document.getElementById(inputId);
  var text = element.value;
  var paramInput = document.getElementById(paramInputId);
  if (paramInput == null) // Params can be missing when input is readonly. So ignore ajax request
    return;
  var parameters = document.getElementById(paramInputId).value;
  
  if (text == marvin.autocomplete.previousText  &&  !forceSuggestions)
    return false;
  
  marvin.autocomplete.previousText = text;
  
  var context = { oldText: text, 
                  inputId: inputId,
                  titlesInputId: titlesInputId, 
                  keyCode: evt.keyCode, 
                  which: evt.which 
                };

  clearTimeout(marvin.autocomplete.timeoutReference);
  
  if (key != marvin.key_enter)
  {
    var suggestionDivIFrame = document.getElementById("marvinSuggestionDiv_iframe");
    marvin.popup.showInPlace(suggestionDivIFrame, element, 0, 20);

    var suggestionDiv = document.getElementById("marvinSuggestionDiv");
    marvin.popup.showInPlace(suggestionDiv, element, 0, 20);
    suggestionDiv.innerHTML = "Henter data....";
  }
  
  
  var f = function () 
          {
            ajax.AjaxUpdate(text, forceSuggestions, parameters, marvin.autocomplete.update_callback, context);
          };

  if (forceSuggestions)
    f();
  else
    marvin.autocomplete.timeoutReference = setTimeout(f, 700); // Delay to avoid calling server on every keystroke
  
  return false;
}


marvin.autocomplete.update_callback = function(response)
{
  if ( response.error != null )
  {
    alert(response.error);
    return;
  }

  var text = response.value[0];
  var suggestions = response.value[1];
  var enableTypeAhead = response.value[2];
  var lineCount = response.value[3];
  var values = response.value[4];
  var titles = response.value[5];

  var oldText = response.context.oldText;
  var inputId = response.context.inputId;
  var titlesInputId = response.context.titlesInputId;
  var key = (document.all ? response.context.keyCode : response.context.which);

  var input = document.getElementById(inputId);
  var titlesInput = document.getElementById(titlesInputId);
  var suggestionDiv = document.getElementById("marvinSuggestionDiv");
  var suggestionDivIFrame = document.getElementById("marvinSuggestionDiv_iframe");
  
  suggestionDiv.innerHTML = suggestions;

  if (suggestionDiv.style.width == '')
    suggestionDiv.style.width = input.style.width;
      
  if (suggestionDivIFrame.style.width == '')
    suggestionDivIFrame.style.width = input.style.width;

  marvin.autocomplete.inputElement = input;
  marvin.autocomplete.inputTitlesElement = titlesInput;
    
  marvin.autocomplete.suggestionDiv = suggestionDiv;
  marvin.autocomplete.suggestionDivIFrame = suggestionDivIFrame;
    
  marvin.disableActivateButton = true;
  
  // Update if: some text is available
  //            and user did not press escape
  //            and user did not change the text while the ajax request was pending
  //            - this happens when typing fast
  if (text != null  &&  text.length > 0 && key != marvin.key_escape && input.value == oldText)
  {
    if (!marvin.isDeletingChar(key)  &&  enableTypeAhead)
      marvin.autocomplete.typeAhead(input, text);
      
    marvin.autocomplete.selectedLineNo = 0;
    marvin.autocomplete.lineCount = lineCount;
    marvin.autocomplete.values = values;
    marvin.autocomplete.titles = titles;
    marvin.autocomplete.highlightSelectedLine(true, 'keyboard');
  }
  else
  {
    suggestionDiv.innerHTML = 'Søgningen gav intet resultat...';
  }
}


marvin.autocomplete.scrolling = false;


marvin.autocomplete.cancelPopup = function()
{
  if ( !marvin.autocomplete.scrolling )
  {
    clearTimeout(marvin.autocomplete.timeoutReference);

    if (marvin.autocomplete.inputElement)
    {
      marvin.autocomplete.inputElement = null;
      
      var suggestionDiv = document.getElementById("marvinSuggestionDiv");
      suggestionDiv.style.visibility = 'hidden';
      
      var suggestionDivIFrame = document.getElementById("marvinSuggestionDiv_iframe");
      suggestionDivIFrame.style.visibility = 'hidden';
      
    }
  }
  
  marvin.autocomplete.scrolling = false;
}


marvin.autocomplete.cancelPopupDelayed = function(delay)
{
  marvin.autocomplete.timeoutReference = setTimeout(function() {marvin.autocomplete.cancelPopup();}, delay);
}


marvin.autocomplete.highlightSelectedLine = function(enable, inputtype)
{
  var liId = "autocompleteLi_" + this.selectedLineNo;
  var liElement = document.getElementById(liId);
  if (enable)
  {
    liElement.className = "selected";
    
    if ( inputtype == 'keyboard' )
      liElement.scrollIntoView(false);

  }
  else
    liElement.className = "";    
}


marvin.autocomplete.moveSelectedLineUp = function()
{
  if (marvin.autocomplete.selectedLineNo > 0)
  {
    marvin.autocomplete.moveSelectedLine(-1);
  }
}


marvin.autocomplete.moveSelectedLineDown = function()
{
  if (marvin.autocomplete.selectedLineNo < marvin.autocomplete.lineCount-1)
  {
    marvin.autocomplete.moveSelectedLine(1);
  }
}


marvin.autocomplete.moveSelectedLine = function(dir)
{
  marvin.autocomplete.highlightSelectedLine(false, 'keyboard');
  marvin.autocomplete.selectedLineNo += dir;
  marvin.autocomplete.highlightSelectedLine(true, 'keyboard');
  marvin.autocomplete.selectItem();
}


marvin.autocomplete.lineHover = function(lineNo)
{
  marvin.autocomplete.highlightSelectedLine(false, 'mouse');
  marvin.autocomplete.selectedLineNo = lineNo;
  marvin.autocomplete.highlightSelectedLine(true, 'mouse');
  marvin.autocomplete.selectItem();
}


marvin.autocomplete.selectItem = function()
{
  if (marvin.autocomplete.inputElement != null)
  {
    var value = marvin.autocomplete.values[marvin.autocomplete.selectedLineNo];
    marvin.autocomplete.inputElement.value = value;
    
    if (marvin.autocomplete.inputTitlesElement != null)
    {
      titleValue = marvin.autocomplete.titles[marvin.autocomplete.selectedLineNo];
      marvin.autocomplete.inputTitlesElement.value = titleValue; 
    }
  }
}


/* ======================================================================================================
  Roll over effects
====================================================================================================== */
marvin.rollover = {};

marvin.rollover.rollover = function(source, cssClass, enable)
{
  if (enable)
  {
    source.className += " "+cssClass;
  }
  else
  {
    // Remove cssClass - apparently Netscape strips leading whitespace in cssClass, so take that into account
    if (marvin.isNetscape)
      source.className = source.className.replace(cssClass,"");
    else
      source.className = source.className.replace(" "+cssClass,"");
  }
}


/* ======================================================================================================
  ColorSelector
====================================================================================================== */
marvin.colorselector = {};

marvin.colorselector.timeout = null;

marvin.colorselector.selectcolor = function(color, divId, targetId, hiddenId)
{
  var target = document.getElementById(targetId);
  target.style.background = color;
  
  var hiddenInput = document.getElementById(hiddenId);
  hiddenInput.value = color;

  marvin.popup.hideId(divId);
}

marvin.colorselector.hideDivIdTimeout = function(divId, time)
{
  marvin.colorselector.timeout = setTimeout(function() { marvin.popup.hideId(divId); } , time); 
}

marvin.colorselector.cancelTimeOut = function()
{
  clearTimeout(marvin.colorselector.timeout);
}


/* ======================================================================================================
  Tables
====================================================================================================== */
marvin.tables = {};

marvin.tables.scrollRowIntoView = function(tableId, rowIndex)
{
  var table = document.getElementById(tableId);
  var row = table.rows[rowIndex];
  
  // Works fine, but unusable when trying to edit something else
  //row.scrollIntoView();
}


/* ======================================================================================================
  Dragging utilities
====================================================================================================== */
marvin.drag = {};

marvin.drag.disableTextSelection = function()
{
	// Ensure cursor movement with mouse down do not function as "select text".
	
	marvin.tableresize.oldOndrag = document.body.ondrag;
	marvin.tableresize.oldOnselectstart = document.body.onselectstart;
	
	document.body.ondrag = function () { return false; };
	document.body.onselectstart = function () { return false; };
}


marvin.drag.enableTextSelection = function()
{
 	document.body.ondrag = marvin.tableresize.oldOndrag;
 	document.body.onselectstart = marvin.tableresize.oldOnselectstart;
}


/* ======================================================================================================
  Row drag
====================================================================================================== */
marvin.rowdrag = {};

// Called OnLoad of page
// Reduces bandwidth: uses javascript to set properties instead of writing them in HTML.
marvin.rowdrag.setupEventHandlers = function(tableId, toolTip)
{
  var table = document.getElementById(tableId);
  var cells;
  if (table)
  {
    cells = table.getElementsByTagName("td");
  }

  if (cells)
  {
    for (var i=0; i<cells.length; ++i)
    {
      var cell = cells[i];
      if (cell.className == "lineno")
      {
        cell.onmouseover = function(evt) { marvin.rollover.rollover(this.parentNode, 'lineno-mouseover', true); }
        cell.onmouseout = function(evt) { marvin.rollover.rollover(this.parentNode, 'lineno-mouseover', false); }
        cell.onmousedown = function(evt) { marvin.rowdrag.dragPress(evt); }
        cell.oncontextmenu = marvin.rowdrag.contextMenu;
        cell.title = toolTip;
      }
      else if (cell.className == "headlineno")
      {
        cell.onmouseover = function(evt) { marvin.rollover.rollover(this.parentNode, 'lineno-mouseover', true); }
        cell.onmouseout = function(evt) { marvin.rollover.rollover(this.parentNode, 'lineno-mouseover', false); }
      }
    }
  }
}

marvin.rowdrag.dragPress = function(evt)
{
	evt = new Evt(evt);
	
	if (evt.button != marvin.button_left)
	  return;
	
	marvin.rowdrag.startCell = evt.source;
	marvin.rollover.rollover(evt.source, 'lineno-dragged', true);

  // Fetch table (tr-tbody-table)	and mark it as "in dragging mode"
	var table = evt.source.parentNode.parentNode.parentNode;
	table.className += " lineno-dragged";
	//alert(table.tagName);
	table.style.cursor = "hand";

  //Evt.addMouseListeners(marvin.rowdrag.dragMove, marvin.rowdrag.dragRelease);
	Evt.addEventListener(document, "mousemove", marvin.rowdrag.dragMove, false);
	Evt.addEventListener(document, "mouseup", marvin.rowdrag.dragRelease, false);
	
	marvin.drag.disableTextSelection();
	
}


marvin.rowdrag.dragMove = function(evt) 
{
	var evt = new Evt(evt);

	evt.consume();
}


marvin.rowdrag.dragRelease = function(evt) 
{
	evt = new Evt(evt);

	// Verify we are moving in same table
	var sameTable = marvin.rowdrag.startCell.parentNode.parentNode == evt.source.parentNode.parentNode;
	if (sameTable)
	{
    var startRowIndex = marvin.rowdrag.startCell.parentNode.rowIndex;
    var endRowIndex = evt.source.parentNode.rowIndex;

    if (startRowIndex != endRowIndex  &&  startRowIndex-1 != endRowIndex)
    {  	
      // Postback the move request  
      marvin.rowdrag.postbackDragRelease(startRowIndex, endRowIndex);
    }
  }
  
  // Fetch table (tr-tbody-table)	and mark it as "in dragging mode"
	var table = marvin.rowdrag.startCell.parentNode.parentNode.parentNode;
	table.className = table.className.replace(" lineno-dragged", "");
	
	marvin.rollover.rollover(marvin.rowdrag.startCell, 'lineno-dragged', false);
	
  marvin.drag.enableTextSelection();

	Evt.removeEventListener(document, "mousemove", marvin.rowdrag.dragMove, false);
 	Evt.removeEventListener(document, "mouseup", marvin.rowdrag.dragRelease, false);
}


marvin.rowdrag.contextMenu = function(evt)
{
  evt = new Evt(evt);
  
  var contextDiv = document.getElementById('marvinLineNoContextMenu');
  var popupDiv = contextDiv.childNodes[0];
  var backgroundDiv = contextDiv.childNodes[1];
  
  var pos = marvin.popup.findPosition(evt.source);

  marvin.popup.showInPosition(contextDiv, pos[0], pos[1], 10, 10);
  
  marvin.rowdrag.contextCell = evt.source;

  // Avoid being killen by previous mouse-out (do it before next line!)
  clearTimeout(marvin.rowdrag.contextMenuTimeoutReference);

  // Remove menu if unused after some time
  marvin.rowdrag.disableContextMenuDelayed(5000);
  
  evt.consume();  
  return false;
}


marvin.rowdrag.mouseOutContextMenu = function()
{
  marvin.rowdrag.disableContextMenuDelayed(1000);
}


marvin.rowdrag.disableContextMenuDelayed = function(delay)
{
  marvin.rowdrag.contextMenuTimeoutReference 
    = setTimeout( function() { marvin.popup.hideId('marvinLineNoContextMenu') }, delay );
}


marvin.rowdrag.mouseOverContextMenu = function()
{
  clearTimeout(marvin.rowdrag.contextMenuTimeoutReference);
}


marvin.rowdrag.contextMenuPostback = function(postbackFunction, paramId, confirmMessage)
{
  if (confirmMessage != null)
    if (!confirm(confirmMessage))
      return;
      
  var rowIndex = marvin.rowdrag.contextCell.parentNode.rowIndex;
  var paramInput = document.getElementById(paramId);
  paramInput.value = rowIndex;
  
  postbackFunction();
}


/* ======================================================================================================
  Table resize
====================================================================================================== */
marvin.tableresize = {};


marvin.tableresize.dragPress = function(tableId, userSettingName, evt) 
{
	evt = new Evt(evt);

	marvin.tableresize.tableDiv = document.getElementById(tableId);
	marvin.tableresize.tableDivHeight = parseInt(marvin.tableresize.tableDiv.style.height);
	marvin.tableresize.userSettingName = userSettingName;
	marvin.tableresize.dragElement = evt.source;
	
	marvin.tableresize.dragStartPosY = evt.y;
	
	Evt.addEventListener(document, "mousemove", marvin.tableresize.dragMove, false);
	Evt.addEventListener(document, "mouseup", marvin.tableresize.dragRelease, false);
	
	marvin.drag.disableTextSelection();
}


marvin.tableresize.dragMove = function(evt) 
{
	var evt = new Evt(evt);

	var deltaY = (evt.y - marvin.tableresize.dragStartPosY);
	var divHeight = parseInt(marvin.tableresize.tableDiv.style.height);
	var newHeight = divHeight + deltaY;

//var x = document.getElementById('_ctl0_Page__ctl5_MainContentControl__ctl1_lines_text');
//x.value = "Y: " + evt.y + "/" + deltaY;// + "  DH: " + divHeight + "/" + newHeight;	

	if (newHeight > 30  &&  newHeight < 2000)
	{
	  marvin.tableresize.tableDiv.style.height = (marvin.tableresize.tableDivHeight + deltaY)+"px";

  	marvin.tableresize.dragElement.scrollIntoView();
  }
	
	evt.consume();
}


marvin.tableresize.dragRelease = function(evt) 
{
	evt = new Evt(evt);

	Evt.removeEventListener(document, "mousemove", marvin.tableresize.dragMove, false);
 	Evt.removeEventListener(document, "mouseup", marvin.tableresize.dragRelease, false);
  
  marvin.drag.enableTextSelection();
	
	// Use Ajax to store new table height
	var divHeight = parseInt(marvin.tableresize.tableDiv.style.height);
	DataGridBrowser.StoreHeight(marvin.tableresize.userSettingName, divHeight);
}

/* ======================================================================================================
  IFrame resize
====================================================================================================== */
marvin.iframeresize = {};

marvin.iframeresize.dragPress = function(iframeId, userSettingName, evt) 
{
	evt = new Evt(evt);
	marvin.iframeresize.iframe = document.getElementById(iframeId);
	marvin.iframeresize.iframeHeight = parseInt(marvin.iframeresize.iframe.style.height);
	marvin.iframeresize.userSettingName = userSettingName;
	marvin.iframeresize.dragElement = evt.source;
  
	marvin.iframeresize.dragStartPosY = evt.y;
  
	Evt.addEventListener(document, "mousemove", marvin.iframeresize.dragMove, false);
  Evt.addEventListener(document, "mouseup", marvin.iframeresize.dragRelease, false);
  
	marvin.drag.disableTextSelection();
}


marvin.iframeresize.dragMove = function(evt) 
{
	var evt = new Evt(evt);

	if(evt.button == marvin.button_left)
  {
	  var deltaY = (evt.y - marvin.iframeresize.dragStartPosY);
	  
	  var height = parseInt(marvin.iframeresize.iframe.style.height);
	  
	  var newHeight = height + deltaY;
   
	  if (newHeight > 0  &&  newHeight < 2000)
	  {
	    marvin.iframeresize.iframe.style.height = (marvin.iframeresize.iframeHeight + deltaY)+"px";
    }
  	
	  evt.consume();	  
	  return false;
	}
}

marvin.iframeresize.dragRelease = function(evt) 
{

	evt = new Evt(evt);
	
	Evt.removeEventListener(document, "mousemove", marvin.iframeresize.dragMove, false);
 	Evt.removeEventListener(document, "mouseup", marvin.iframeresize.dragRelease, false);
  
  marvin.drag.enableTextSelection();
	
	// Use Ajax to store new iframe height
	var height = parseInt(marvin.iframeresize.iframe.style.height);
	ResizableIFrame.StoreHeight(marvin.iframeresize.userSettingName, height);
}

/* ======================================================================================================
  Table functions
====================================================================================================== */
marvin.infoRow = {};


marvin.infoRow.hide = function(elementId)
{
  var element = document.getElementById(elementId);
  element.style.display = 'none';
}

marvin.infoRow.show = function(elementId)
{
  var element = document.getElementById(elementId);
  element.style.display = 'inline';
}



marvin.infoRow.showInfoRow = function(elementId, tableColumns, dataKey, ajax)
{
  var element = document.getElementById(elementId);
  var row = element.parentNode.parentNode;
  var table = row.parentNode.parentNode;
  var newRowIndex = row.rowIndex + 1;
  var newRow = table.insertRow(newRowIndex);
  var newCell = newRow.insertCell(0);
  newCell.style.padding = '0px';
  newCell.style.margin = '0px';
  newCell.colSpan = tableColumns;
  newCell.innerHTML = '<div id="infoRowDiv' + dataKey + '" class="infoRowDiv">Henter data...</div>'; 
  
  ajax.UpdateInfo(dataKey, marvin.infoRow.updateInfo_callback);
}

marvin.infoRow.hideInfoRow = function(elementId)
{
  var element = document.getElementById(elementId);
  var row = element.parentNode.parentNode;
  var table = row.parentNode;
  var rowIndex = row.rowIndex + 1;
  table.deleteRow(rowIndex);
}

marvin.infoRow.updateInfo_callback = function(response)
{
  if ( response.error != null )
  {
    alert(response.error);
    return;
  }

  var text = response.value[0];
  var dataKey = response.value[1];
  
  var divElement = document.getElementById("infoRowDiv" + new String(dataKey));
  divElement.innerHTML = text;
}

/* ======================================================================================================
  Data Lookup functions
====================================================================================================== */
marvin.ajaxdatalookup = {};

marvin.ajaxdatalookup.getContents = function(id, parameterString, ajax)
{      
  ajax.GetContents(id, parameterString, marvin.ajaxdatalookup.getContents_callback);
}


marvin.ajaxdatalookup.getContents_callback = function(response)
{
  if ( response.error != null )
  {
    alert(response.error +"\n" + response.request.responseText);
    return;
  }

  var text = response.value[0];
  var id = response.value[1];
  
  var spanFrame = document.getElementById(new String(id));
  spanFrame.innerHTML = text;
}

/* ======================================================================================================
 Marvin Dragdrop 
====================================================================================================== */
marvin.dragdrop = {};
marvin.dragdrop.dragging;

marvin.dragdrop.param1;
marvin.dragdrop.param2;


marvin.dragdrop.start = function(id, param, hiddenId)
{
  hiddenId.value = param;
  marvin.dragdrop.param1 = param;
  marvin.dragdrop.dragging = true;
  
  marvin.drag.disableTextSelection();
}

marvin.dragdrop.end = function(id, param, hiddenId)
{
    if( marvin.dragdrop.dragging )
    {
      hiddenId.value = param;
      marvin.dragdrop.param2 = param;
      marvin.dragdrop.dragging = false;
      marvin.dragdrop.postbackDragRelease(marvin.dragdrop.param1, marvin.dragdrop.param2);
    }
}

marvin.dragdrop.over = function(id, param)
{
  if( marvin.dragdrop.dragging )
  {
    id.className = " dragdropOver";
  }
}

marvin.dragdrop.out = function(id, param)
{
  if( marvin.dragdrop.dragging )
  {
	  id.className = id.className.replace(" dragdropOver", "");
  }
}

/* ======================================================================================================
 Editable Literal
====================================================================================================== */
marvin.editableLiteral = {};

marvin.editableLiteral.oldOnSubmit;

marvin.editableLiteral.showTextBox = function(textInputID, literalSpanID, editSpanID, saveImageID)
{
  var literalSpan = document.getElementById(literalSpanID);
  var editSpan = document.getElementById(editSpanID);
  var textInput = document.getElementById(textInputID);

  var pos = marvin.popup.findPosition(literalSpan);
  
  literalSpan.style.visibility = 'hidden';
  editSpan.style.display = 'block';
  editSpan.style.whiteSpace = 'nowrap';
  editSpan.style.position = 'absolute';
  editSpan.style.top = pos[1] + 'px';
  editSpan.style.left = pos[0] + 'px';
  
  var text = literalSpan.innerHTML;
  
  while (text.toLowerCase().indexOf('<br>', 0) != -1)
  {
    text = text.replace('<br>', '\r\n');
    text = text.replace('<BR>', '\r\n');
  }
  
  textInput.value = text;  
  textInput.focus();
  textInput.select();
}

marvin.editableLiteral.handleKeyDown = function(e, saveImageID, textInputID, literalSpanID, editSpanID, ajax, parameterString, type, emptyText)
{
  if (!marvin.NotEnterPressed(e) && type != "textarea")
  {
    marvin.editableLiteral.saveChange(parameterString, textInputID, literalSpanID, editSpanID, ajax, emptyText);
    return false;
  }
  else if (e.keyCode == marvin.key_escape)
  {
    marvin.editableLiteral.cancelEdit(textInputID, literalSpanID, editSpanID);
    return false;
  }
  else
  {
    return true;
  }
}

marvin.editableLiteral.cancelEdit = function(textInputID, literalSpanID, editSpanID)
{
  var literalSpan = document.getElementById(literalSpanID);
  var editSpan = document.getElementById(editSpanID);

  literalSpan.style.visibility = 'visible';
  editSpan.style.display = 'none';
}

marvin.editableLiteral.saveChange = function(parameterString, textInputID, literalSpanID, editSpanID, ajax, emptyText)
{

  var literalSpan = document.getElementById(literalSpanID);
  var editSpan = document.getElementById(editSpanID);
  var textInput = document.getElementById(textInputID);
  
  ajax.SaveChange(textInput.value, literalSpanID, parameterString, emptyText, marvin.editableLiteral.saveChange_callback);
  
  literalSpan.style.visibility = 'visible';
  literalSpan.innerHTML = 'Gemmer...';
  
  editSpan.style.display = 'none';
}

marvin.editableLiteral.saveChange_callback = function(response)
{

  var literalSpan = document.getElementById(response.value[0]);
  var text = response.value[1];
  literalSpan.innerHTML = text;
}

/* ======================================================================================================
 Context Menu
====================================================================================================== */

marvin.contextMenu = {};

//document.onclick = function() {hideContextMenu();}

marvin.contextMenu.KeySelected = null;
marvin.contextMenu.Display = false;

marvin.contextMenu.hideContextMenu = function(contextMenuId)
{
  if (!marvin.contextMenu.Display)
  {
    var contextMenu = document.getElementById(contextMenuId);
    contextMenu.style.display = 'none';
  }
  marvin.contextMenu.Display = false;
}

marvin.contextMenu.showContextMenu = function(contextMenuId, element, key, e)
{
  marvin.contextMenu.Display = true;
  marvin.contextMenu.KeySelected = key;
  
  document.onclick = function() {marvin.contextMenu.hideContextMenu(contextMenuId);}
  
  var contextMenu = document.getElementById(contextMenuId);
  var cursorPos = marvin.getCursorPosition(e);
  
  contextMenu.style.display = 'block';
  contextMenu.style.position = 'absolute';
  contextMenu.style.left = cursorPos.x + 'px';
  contextMenu.style.top = cursorPos.y + 'px';
}

marvin.contextMenu.handleItemClicked = function(action, commandArgumentId, commandNameId)
{
  var commandArgumentElem = document.getElementById(commandArgumentId);
  var commandNameElem = document.getElementById(commandNameId);
  
  commandArgumentElem.value = marvin.contextMenu.KeySelected;
  commandNameElem.value = action;
 
  handleContextMenuAction();
}

marvin.contextMenu.handleItemClientFunction = function(callFunction)
{
  var commandArgument = marvin.contextMenu.KeySelected;
  
  callFunction = callFunction.replace("$commandArgument$", commandArgument);
  
  eval(callFunction);
}
