// ab.js
// client-side functions for EBlock:AdminBar web control

var browser_ie = (navigator.appVersion.indexOf("MSIE") != -1);
var browser_moz = (navigator.appVersion.indexOf("Mozilla/5.0") != -1) ||
  ((navigator.appVersion.indexOf("5.0") != -1) && !browser_ie); // for phoenix
var browser_safari = (navigator.appVersion.indexOf("Safari") != -1);

var abBarClosed       = 0;
var abBarOpen         = 1;
var abBarExpanding    = 2;
var abBarExpanded     = 3;

var abBarState        = abBarClosed;

var abHeightCurrent   = 0; // current ab width
var abHeightPrevious  = 0;
var abHeightVisible   = 46; // ab width when shown
var abHeightOpen      = 46;
var abHeightExpanding = abHeightOpen + 21;
var abHeightExpanded  = abHeightExpanding + 200;
var abDeltaMaximised  = 44;
var abMaximised       = false;
var abIsMaximising    = false;

var abPageIsDirty     = false;
var abPageRevisedUrl;
var abPaneModified    = false;
var abPaneEmpty       = true;
var abLockResize      = false;

// **** functions for showing panes ****

var ebTaskHistory = new Array();

// constructs a new task object
function ebNewTask(pane, group, name, shortname, item, action, params) {
  var newTask = new Object();
  newTask.pane = pane;
  newTask.group = group;
  newTask.name = name;
  newTask.shortname = shortname;
  newTask.item = item;
  newTask.action = action;
  newTask.params = params;
  return(newTask);
  }
  
// standard call to show given task in admin bar
function ebDoAdminTask(taskId) {
  return abShowPaneById(taskId);
  }

// shows given task in admin bar given a task id
function abShowPaneById(taskId) {
  return abShowPane(ebAdminTasks[taskId]);
  }

// shows given task in admin bar given a task object  
function abShowPane(task) {
  if (task != null) {
    // set pane title in header
    var headTitle = document.getElementById("ebAbTitle");
    headTitle.innerHTML = "Loading...";
    // set pane frame source
    var paneFrame = document.getElementById("ebAbFrame");
    var paneUrl = task.pane + "?id=" + task.item
    if (task.action != "") paneUrl += "&action=" + task.action
    if (task.params != "") paneUrl += "&" + task.params
    paneFrame.contentWindow.document.location.replace(paneUrl);
    // expand bar
    if (abBarState != abBarExpanding) abOpen(abBarExpanding, true);
    abPaneEmpty = false;
    // push task onto history
    ebTaskHistory.push(task);
  }
  return false;
}

// shows the previous pane from pane history
function abPreviousPane() {
  // pop off current pane
  ebTaskHistory.pop();
  // get previous task
  var task = ebTaskHistory.pop();
  if (task != null) {
    abShowPane(task);
    }
  }
  
// clearst the admin bar task pane
function abClearPane() {
  if (!abPaneEmpty) {
    // clear pane title
    var headTitle = document.getElementById("ebAbTitle");
    headTitle.innerHtml = "";
    // clear pane source
    var paneFrame = document.getElementById("ebAbFrame");
    paneFrame.contentWindow.document.location.replace("about:blank");
    
    document.getElementById("ebAbModified").style.display = "none";
    abPaneEmpty = true;
    }
  }

// **** standard callback functions from panes ****

// called at the start of a pane load operation
function ebStartLoad() {
  document.getElementById("ebAbBusy").style.display = "block";
  }

// called upon completion of a pane load operation
function ebPaneLoaded(spareParam, updatedPaneHeight) {
  ebPaneResized(updatedPaneHeight);
  abOpen(abBarExpanded, true);
  }

function ebPaneResized(paneHeight) {
  document.getElementById("ebAbFrame").style.height = paneHeight + "px";
  abHeightExpanded = abHeightExpanding + paneHeight;
  }

// sets the title of the admin pane
function ebSetTitle(title) {
  if (title != "") {
    var headTitleDiv = document.getElementById("ebAbTitle");
    headTitleDiv.innerHTML = title;
    }
  }

// sets the modified indicator and dirty flag on the admin bar
function ebSetModified() {
  document.getElementById("ebAbModified").style.display = "block";
  abPaneModified = true;
  abPageIsDirty = true;
  }
  
// clears the modified indicator on the admin bar
function ebClearModified() {
  var modifiedEl = document.getElementById("ebAbModified")
  if (modifiedEl) { modifiedEl.style.display = "none"; }
  abPaneModified = false;
  }
  
// warns user about unsaved modifications
function ebWarnModified() {
  if (abPaneModified) {
    if (window.confirm("You have made changes that have not yet been saved.\n\n" +
        "Click OK to continue and lose the changes you have made, or to\n" +
        "save your changes, click Cancel and then click the Save button.")) {
      ebClearModified();
      return true;
      }
    else {
      return false;
      }
    }
  else {
    return true;
    }
  }

// sets the dirty flag for the admin bar. this forces reload
// of the page when the admin bar is closed
function ebSetDirtyFlag(revisedUrl) {
  abPageIsDirty = true;
  abPageRevisedUrl = revisedUrl
  }

// closes the current task pane
function ebClosePane() {
  if (ebWarnModified()) {
    abClose(true);
    }
  }

// shows the current pane if loading did not complete correctly
function ebDebugPane() {
  ebPaneLoaded("Debug", 400);
  }
  
// **** functions for ab hotkey CTRL + K or CTRL + . ****

var ctrlDown = false;
if (document.layers) {
  document.captureEvents(Event.KEYDOWN);
  document.captureEvents(Event.KEYUP); } // FOR NS 4.0
  
document.onkeydown = function keyPress(evt) {
  if(!evt) { // IE
   var keyCode = window.event.keyCode;
  } else { // Mozilla
    var keyCode = evt.keyCode;
  }
  if (keyCode == 17) ctrlDown = true;
  if ((keyCode == 75 || keyCode == 190) && ctrlDown) abOpen(abBarOpen, false);
}  
document.onkeyup = function keyPress(evt) {
  if (!evt) { //IE
    var keyCode = window.event.keyCode;
  } else { // Mozilla
   var keyCode = evt.keyCode;
  }
  if (keyCode == 17) ctrlDown = false;
  if ((keyCode == 75 || keyCode == 190) && ctrlDown) abOpen(abBarOpen, false);
}

function abSetCookie(name,value,days)
{
	if (days)
	{
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function abGetCookie(name)
{
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++)
	{
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

// **** functions for positioning admin bar ****

// pegs used to store event handlers while admin bar events are hooked up
var abResizeEventPeg;
var abScrollEventPeg;
var abEventsHooked = false;

// repositions the admin bar after window resize
function abReposition() {
  var docEl = document.documentElement;
  var holdEl = document.getElementById("ebAbHold");
  var barEl = document.getElementById("ebAbHoldInt");
  var frameEl = document.getElementById("ebAbFrame");
  
  var windowWidth = 0;
  if (document) {
    if( typeof(window.innerWidth) == 'number' ) {
      // Mozilla etc.
      windowWidth = window.innerWidth;
      }
    else {
      if (document.documentElement && document.documentElement.clientWidth) {
        //IE 6+ in 'standards compliant mode'
        windowWidth = document.documentElement.clientWidth;
        }
      else {
        if (document.body && document.body.clientWidth) {
          //IE 4 compatible
          windowWidth = document.body.clientWidth;
          }
        }
      }
    }
  
  holdEl.style.width = windowWidth + "px";
  
  if (abMaximised) {
    // make bar occupy entire window width
    barEl.style.left = "0px";
    barEl.style.width = windowWidth + "px";
    if (frameEl) frameEl.style.width = windowWidth + "px";
    }
  else {
    var barWidth = windowWidth * 0.85;
    if (barWidth < 32) barWidth = 16;
    if (barWidth > 800) barWidth = 800;
    barEl.style.left = Math.floor(docEl.scrollLeft + (windowWidth - barWidth) / 2) + "px";
    barEl.style.width = Math.floor(barWidth) + "px";
    if (frameEl) frameEl.style.width = Math.floor(barWidth) + "px";
    }
  window.scrollTo(0, 0);
  
  var paneWindow = window.frames.ebAbFrame;
  if (paneWindow != null) {
    if (paneWindow.paneResize != null) {
      paneWindow.paneResize();
      }
    }
  }

// called on window resize

function abResize() {
  if (!abLockResize) {
    var paneWindow = window.frames.ebAbFrame;
    if (paneWindow) {
      if (paneWindow.calculatePaneHeight) {
        paneWindow.calculatePaneHeight();
        
        }
      }    
    abReposition();
    
    // resize bar skipping animation
    abHeightVisible = abHeightExpanded;
    if (!abIsMaximising) abEndSlide();
    }
  }

// called on admin bar zoom  
// CALLED TWICE ON RESTORE I THINK
function abZoom() {
  abLockResize = true;
    
  abIsMaximising = true;
  abMaximised = !abMaximised;
  
  abSetCookie("ebAbZoom", abMaximised, 100);
  
  //if (abMaximised) {
    var paneWindow = window.frames.ebAbFrame;
    if (paneWindow) {
      if (paneWindow.calculatePaneHeight) {
        paneWindow.calculatePaneHeight(); 
        }
      }  
  //  }
  abReposition();

  // animate bar resize
  abOpen(abBarExpanded, true);
  abLockResize = false;
  
  if (abMaximised) {
    // show restore icon
    document.getElementById("ebAbZoom").className = "maximised"; }
  else {
    // show zoom icon
    document.getElementById("ebAbZoom").className = ""; }
  }


// repositions the admin bar after window scroll
function abScroll() {
  //document.getElementById("ebAbHold").style.top = document.documentElement.scrollTop + "px";
  }

// hooks up page events needed by the admin bar whilst visible
function abHookEvents() {
  if (!abEventsHooked) {
    document.documentElement.style.overflow = "hidden";
    abLockResize = true;
    
    abResizeEventPeg = window.onresize;
    window.onresize = abResize;
    abScrollEventPeg = window.onscroll;
    window.onscroll = abScroll;
    abEventsHooked = true;
    abReposition();
    
    abLockResize = false;
    }
  }

// unhooks admin bar page events once admin bar closed
function abUnhookEvents() {
  if (abEventsHooked) {
    document.documentElement.style.overflow = "auto";
    
    // rehook old events
    window.onresize = abResizeEventPeg;
    window.onscroll = abScrollEventPeg;
    // fire resize event in case window dimensions have changed
    if (abResizeEventPeg) abResizeEventPeg();
    abEventsHooked = false;
    }
  }

  
// **** functions for opening, closing and animating admin bar ****

var slideAniLen = 250;
var slideHideDelay = 500;
var slideAccelConstant;
var slideReveal = false;
var slideStartTime;
var slideAniTimer;
var abHideTimer;
var minCPUResolution = 10;
  
// reveals admin bar when hidden
function abOpen(state, forceAction) {
  var oldState = abBarState;
  if (abHideTimer) window.clearTimeout(abHideTimer);
  if (forceAction || (abBarState == abBarClosed)) {
    
    if (oldState == abBarClosed && abGetCookie("ebAbZoom") == "true") {
      // set zoom if cookie set
      abMaximised = true;
      var elZoom = document.getElementById("ebAbZoom");
      if (elZoom) elZoom.className = "maximised";
      }
      
    // hook up window events needed by admin bar
    abHookEvents();
    
    // show holder div
    document.getElementById("ebAbHold").style.display = "block";
    // start slide
    abBarState = state;
    switch(abBarState) {
      case 0 : abHeightVisible = abHeightHidden; break;
      case 1 : abHeightVisible = abHeightOpen; break;
      case 2 : abHeightVisible = abHeightExpanding;
        document.getElementById("ebAbBusy").style.display = "block";
        break;
      case 3 : abHeightVisible = abHeightExpanded;
        document.getElementById("ebAbBusy").style.display = "none";
    }
    if (browser_ie || browser_moz) { abStartSlide(state >= oldState); } else { abEndSlide(); }
    }
  }
  
// closes admin bar
function abClose(forceAction) {
  if (forceAction || (abBarState != abBarClosed)) {
    if (abHideTimer) window.clearTimeout(abHideTimer);
    // unhook window events
    abBarState = abBarClosed;
    abHeightVisible = 0;
    var busyEl = document.getElementById("ebAbBusy")
    if (busyEl) busyEl.style.display = "none";
    if (browser_ie || browser_moz) { abStartSlide(false); } else { abEndSlide(); }
    }
  }

// clears admin bar close timer on mouse over
function abMouseOver() {
  if (abBarState == abBarOpen) {
    if (abHideTimer) window.clearTimeout(abHideTimer);
    }
  }

// sets admin bar close timer on mouse out
function abMouseOut() {
  if (abBarState == abBarOpen) {
    if (abHideTimer) window.clearTimeout(abHideTimer);
    abHideTimer = window.setTimeout("abClose(false)", slideHideDelay);
    } 
  }
  
// starts admin bar animation 
function abStartSlide(doReveal) {
  abHeightPrevious = abHeightCurrent;
  slideReveal = doReveal;
  slideStartTime = (new Date()).getTime();
  slideAccelConst = (abHeightVisible - abHeightPrevious) / slideAniLen / slideAniLen;
  window.clearInterval(slideAniTimer);
  slideAniTimer = window.setInterval("abSlide();", minCPUResolution);
  }
  
// forces admin bar animation to end
function abEndSlide() {
  window.clearInterval(slideAniTimer);
  abMoveTo(abHeightVisible);
  switch (abBarState) {
    case 0 :
      abClearPane();
      // clear task history
      ebTaskHistory = new Array();
      // reload page on bar close if dirty flag set
      if (abPageIsDirty) {
        abPageIsDirty = false;
        //var elReload = document.getElementById("ebAbReload");
        //if (elReload) elReload.style.display = "block";
        if (abPageRevisedUrl) {
          document.location.replace(abPageRevisedUrl); }
        else {
          document.location.replace(document.location.href); }
        }
      abUnhookEvents();
      break;
    case 1 :
      var userInput = document.getElementById("ebAbUser");
      if (userInput) {
        // focus username input if login required
        userInput.focus();
        // scroll adminbar div back to top after focus
        document.getElementById("ebAbBar").scrollTop = 0;
        document.documentElement.scrollTop = 0;
        }
      break;
    case 3 :
       if (abIsMaximising && !abMaximised) {
        var paneWindow = window.frames.ebAbFrame;
        if (paneWindow) {
          if (paneWindow.calculatePaneHeight) {
            paneWindow.calculatePaneHeight(); 
            }
          }  
        }
        abReposition();
      break;
    }
  abIsMaximising = false;
  }

// controls animation of admin bar
function abSlide() {      
  var elapsed = (new Date()).getTime() - slideStartTime;
  if (elapsed > slideAniLen) abEndSlide();
  else {
    var d = Math.round(Math.pow(slideAniLen-elapsed, 2) * slideAccelConst);
    abMoveTo(abHeightVisible - d);
    }
  }

// animates admin bar
function abMoveTo(x) {
  var hld = document.getElementById("ebAbHold");
  var ab = document.getElementById("ebAb");
  var fr = document.getElementById("ebAbFrame");
  abHeightCurrent = x;
  
  var delta = 0;
  if (abHeightCurrent > abHeightOpen) {
    if (abIsMaximising && !abMaximised) {
      delta = abDeltaMaximised - Math.floor(abDeltaMaximised / (abHeightCurrent / abHeightExpanded));
      }
    else if (abMaximised) {
      delta = Math.floor(abDeltaMaximised * (abHeightCurrent / abHeightExpanded)); }
  }
  
  hld.style.height = (abHeightCurrent - delta) + "px";
  if (abHeightCurrent <= abHeightOpen) {
    ab.style.top = (abHeightCurrent - abHeightOpen) + "px";
    //ab.style.height = abHeightOpen;
  } else {
    if (abMaximised || abIsMaximising) {
      ab.style.top = (-delta) + "px";
      }
    else {
      ab.style.top = "0px";
      }
    if (fr) fr.style.top = (abHeightExpanding - (abHeightExpanded - abHeightCurrent)) + "px";
    //ab.style.height = (abHeightCurrent - abHeightVisible) + "px";
  }
}
