
/*
 * Prototype Element extensions
 */
Element.addMethods({
  /**
	 * Returns the last delimited portion of the dom id or element passed where element id is of the form:
	 *   example-<id> OR example_<id> // Delimited with hypen '-' or underscore '_'
	 * or null if the element id is missing or does contain a delimiter. For example:
	 *   example-25			// Returns 25
	 *   test-example-25	// Returns 25
	 *   test_example_25	// Returns 25
	 *   25					// Returns null - reference element.id instead
	 *   test				// Returns null
	 *   <missing or empty>	// Returns null
	 */
  modelId: function(element) {
    var id = $(element).id;
    if (id == null) return null; // Just in case; browsers tested return empty string for missing id.

    var idParts = id.split(/[-_]/g); // Split on hyphens and underscores
    return (idParts.length > 1) ? idParts.last() : null;
  },
  descendantsMatching: function(element, selector) {    
    return element.descendants().select(function(d){ return d.match(selector)}.bind(this));
  }
});

/* 
 * PLM namespace for home-grown libraries.
 * As we grow more custom code, we should put it here to avoid collisions.
 */
PLM = {
  // Wraps Prototype's syntax for registering functions for onload. Preferred impl has changed several
  // times and still sucks; this is shorthand for observe call and insulates us from further changes.
  init: function(functionToRunOnLoad) {
    document.observe("dom:loaded", functionToRunOnLoad);
  },
  // Returns array of ids for multiple elements.
  ids: function(elements) {
    return elements.invoke('modelId');
  },
  errorAlert: function() {
    alert("An error has occurred. Please try again. If the error persists, contact support@patientslikeme.com for help.");
  },
  // Removes each element in the array from the DOM and returns the array of removed elements.
  removeAll: function(elemArray) {
    var results = [];
    elemArray.each(function(elem) {
      results.push(elem.remove());
    });
	
    return results;
  },
  // Swaps two elements in the DOM.
  // If arrays of elements are passed, swaps elements in the same positions in the arrays with each other.
  domSwap: function(elem1, elem2) {
    if (elem1 instanceof Array) {
      // Swap elements in the same positions in the arrays with each other
      if (elem1.length != elem2.length) {
        throw "Number of elements in arrays to swap does not match";
      }
			
      for (var i=0; i<elem1.length; i++) {
        swap(elem1[i], elem2[i]);
      }
    }
    else {
      // Simply swapping individual elements
      swap(elem1, elem2);
    }
		
    function swap(elem1, elem2) {
      var nextSibling = elem1.nextSibling;
      var parentNode = elem1.parentNode;
      elem2.parentNode.replaceChild(elem1, elem2);
      parentNode.insertBefore(elem2, nextSibling);
    }
  },
  Element: {
    initStorage: function(selector){
      $$(selector).each(function(e){
        e.getStorage().initialize($H(e.attributes['data-store'].value.evalJSON()));
      })
    }
  },
  //extend Ajax.Updater to allow replacement instead of insertion.
  Ajax: {
    Replacer: Class.create(Ajax.Updater, {
      initialize: function($super, container, url, options) {
        options = options || {};
        options.onSuccess = (options.onSuccess || Prototype.emptyFunction).wrap(function(proceed, transport, json){
          $(container).replace(transport.responseText);
          proceed(transport, json);
        })
        $super({
          success: container
        }, url, options);
      }
    }),
    ReplaceAll: Class.create(Ajax.Updater, {
      initialize: function($super, containers, url, options) {
        options = options || {};
        options.onSuccess = (options.onSuccess || Prototype.emptyFunction).wrap(function(proceed, transport, json){
          $$(containers).invoke('replace', transport.responseText);
          proceed(transport, json);
        })
        $super({
          success: containers
        }, url, options);
      }
    }),
    sessionExpired: function(response) {
      return response.status == 401;
    },
    validationError: function(response) {
      return response.status == 422;
    }
  },
  Form: {    
    updateStateField: function(element, form, state_field, initial_term, selectedState){
      var url = '/patients/update_state_field/' + escape(element.value)+ '?form='+form+'&field='+state_field+'&initial_term='+initial_term;
      if (selectedState && !selectedState.blank()) {
        url += '&state=' + selectedState;
      }
		
      new Ajax.Request(url, {
        method: 'get'
      })
    }
  },
  Notify: {
    good: function(message, targetDomId){
      PLM.Notify.notify('confirmed', message, targetDomId);
    },
    bad: function(message, targetDomId){
      PLM.Notify.notify('error', message, targetDomId);
    },
    notify: function(noticeClass, message, targetDomId){
      if (typeof targetDomId == 'undefined') {
        targetDomId = 'ajax-messages';
      }
      $$('.notification').invoke('hide'); // Hide any existing messages
      $(targetDomId).addClassName(noticeClass).update(message).show();
    }
  },
  Window: {
    create: function(container,title,focus,options){
      var window_header = $div({
        className: 'window_header'
      });
      var window_title = $div({
        className: 'window_title'
      });
      var window_close = $div({
        className: 'window_close'
      });
      var window_contents = $div({
        className: 'window_contents'
      });
	 
      var w = new Control.Modal(container,Object.extend({
        className: 'plm_window rx-drop-down',
        closeOnClick: window_close,
        method: 'get',
        insertRemoteContentAt: window_contents,
        afterOpen: function(){
          var newTitle = w.container.down('span.title');
          if(newTitle)
            title = newTitle.innerHTML;
          window_title.update(title);
          var form = w.container.down('form');
          if(focus && form){
            form.focusFirstElement();
          }
        }
      },options || {}));
      w.container.insert(window_header);
      window_header.insert(window_title);
      window_header.insert(window_close);
      w.container.insert(window_contents);
      return w;
    }
  }
}

var Disease = {
  ALS: 1,
  HIV: 5,
  Epilepsy: 11
}
var Role = {
  Patient: 1,
  Caregiver: 5
}

var MyUtils = {
  clear_options: function(select){
    $A(select.options).each(function(o) {
      o.selected = false;
    });
  },
  select_option: function(select, value){
    select.childElements().each(function(o) {
      if(o.value == value){
        o.selected = true
      }
    })
  },
  selected_option: function(select){
      return select.options[select.selectedIndex].text;
  },
  toggleTo: function(el,onoff){    
    onoff ? el.show() : el.hide();
    return el;
  }
}
Element.addMethods(MyUtils);


// troublesome clients
var plmIphone = (navigator.userAgent.toLowerCase().indexOf('iphone') != -1);
var plmIe = document.all && !window.opera;
var plmIe6 = plmIe && !window.XMLHttpRequest;
var plmIe7 = plmIe && !window.JSON;
var plmIe8 = plmIe && window.JSON;

// preload JS generated images
if(document.images) {
  p7 = new Image(19,16);
  p7.src = '/images/icon_closable.gif';
  
  p8 = new Image(15,9);
  p8.src = '/images/yah_arrow_bot.gif';
  
  p9 = new Image(15,9);
  p9.src = '/images/tip_arrow_top.gif';
  
  p10 = new Image(15,9);
  p10.src = '/images/tip_arrow_bot.gif';
  
  p11 = new Image(62,27);
  p11.src = '/images/slide_button_rhs_on.png';
  
  p12 = new Image(396,27);
  p12.src = '/images/slide_button_lhs_on.png';
  
  p13 = new Image(16,16);
  p13.src = '/images/indicator.gif';
}

// define xb styles
var xbListDisplay = (document.all) ? "block" : "list-item";
var xbShow = (document.layers) ? "show" : "visible";
var xbHide = (document.layers) ? "hide" : "hidden";
var xbTrShow = (document.all) ? "block" : "table-row";
var xbTbodyShow = (document.all) ? "block" : "table-row-group";
var xbCursorHand = (document.all) ? "hand" : "pointer";

// define cross browser style object
function xbStyleObj(el)
{
  var element = xbObj(el);
  return (element && element.style) ? element.style : element;
}

// define cross browser object
function xbObj(el)
{
  if (typeof el != 'string')
    return el;
	
  if(document.getElementById)
    return document.getElementById(el);
  else if(document.all)
    return document.all[el];
  else if(document.layers)
    return false;
  else
    return false;
}

// display block
function showDisplay(el) {
  $(el).style.display = "block";
}

// display none
function hideDisplay(el) {
  $(el).style.display = "none";
}

// toggle display
function toggleDisplay(el) {
  if($(el).style.display == "block")
    hideDisplay(el);
  else
    showDisplay(el);
}

function toggleBlind(el)
{
  if(!document.all && !window.opera) {
    if($(el).style.display == "none") {
      if(document.all && !window.opera)
        showDisplay(el);
      else
        new Effect.BlindDown(el);
    } else {
      if(document.all && !window.opera)
        hideDisplay(el);
      else
        new Effect.BlindUp(el);
    }
  }
}

function hideLayer(el) {	
  $(el).style.visibility = 'hidden';
  toggleSelectBoxes('visible', el);
}

function showLayer(el) {	
  $(el).style.visibility = 'visible';
  toggleSelectBoxes('hidden', el);
}

function toggleVisibility(el) {
  if($(el).style.visibility == 'visible')
    hideLayer(el);
  else
    showLayer(el);
}
function toggleSelectBoxes(visibleState, el) {
  if(document.all && !window.XMLHttpRequest && !window.opera) {
    var sel = $$('#content-wrapper select');
    sel.each(function(selectbox) {
      selectbox.style.visibility = visibleState;
    });
    if(el) {
      var visibleSelects = $$('#' + el + ' select');
      visibleSelects.each(function(selectbox) {
        selectbox.style.visibility = 'visible';
      });
    }
  }
}
function swapClassName(el,className) {
  xbObj(el).className = className;
}

function plmToggleClassName(el,startingClass,endingClass) {
  var objClass = xbObj(el).className;
  if(objClass == startingClass)
    swapClassName(el,endingClass);
  else
    swapClassName(el,startingClass);
}

// enhanced PPK findPos scripts
// supposed to work well in Safari

function findPosX(obj) {
  var curleft = 0;

  if(obj.offsetParent)
    while(1)
    {
      curleft += obj.offsetLeft;
      if(!obj.offsetParent)
        break;
      obj = obj.offsetParent;
    }
  else if(obj.x)
    curleft += obj.x;
  return curleft;
}

function findPosY(obj) {
  var curtop = 0;
	
  if(obj.offsetParent)
    while(1)
    {
      curtop += obj.offsetTop;
      if(!obj.offsetParent)
        break;
      obj = obj.offsetParent;
    }
  else if(obj.y)
    curtop += obj.y;
  return curtop;
}


// find position of element to set
function findPos(el,lnk,xOffset,yOffset) {
  var a = $(lnk);
  var s = $(el).style;
  var p = $(el);
		
  // calculate right edge and correct position to keep onscreen
  var xCorrection = 0;

  if(document.getElementById) {
    s.left = ((findPosX(a) + xOffset) - xCorrection) + "px";
    s.top = (findPosY(a) + yOffset) + "px";
  }
}

function showCloseButton(el) {
  new Insertion.Top(el, '<a title="Close this bubble" href="#" onclick="hideLayer(\'toolTip\'); return false"><img src="/images/icon_closable.gif" alt="" class="tip-close-btn" /></a>');
}

function showDropShadow(el) {
  if(window.XMLHttpRequest)
    new Insertion.Top(el, '<div class="tip-shadow"></div>');
}
function hideDropShadow(el) {
  if(window.XMLHttpRequest) {
    var tip = el.getElementsByTagName("div");
    for(var i=0; i<tip.length; i++)
      if(tip[i].className == "tip-shadow")
        tip[i].display = "none";
  }
}
function showHintPointer(el) {
  new Insertion.Bottom(el, '<span class="hint-pointer">&nbsp;</span>');
}

function showYahArrow(el) {
  new Insertion.Top(el, '<img src="/images/yah_arrow_bot.gif" class="yah-arrow-bot" />');
  xbObj(el).className = "nav-box yah-box";
}

var strBubbleArrowTop = '<div id="pointer-arrow" class="tip-arrow"><img src="/images/tip_arrow_top.gif" /></div>';
var strBubbleArrowBot = '<div id="pointer-arrow" class="tip-arrow-bot"><img src="/images/tip_arrow_bot.gif" /></div>';
var strBubbleArrowRight = '<div id="pointer-arrow" class="tip-arrow-right"><img src="/images/tip_arrow_top.gif" /></div>';

function showBubbleArrow(tipDiv,yOffset,xAlign) {
  if(yOffset > 0)
    if(xAlign == "right")
      arrowDir = strBubbleArrowRight;
    else
      arrowDir = strBubbleArrowTop;
  else
    arrowDir = strBubbleArrowBot;
  new Insertion.Top(tipDiv, arrowDir);
  showCloseButton(tipDiv);
  showDropShadow(tipDiv);
}

// global var referring to tooltip
var ttPlm;
// adjust IE offsetLeft
var adjustIeX = 0;
var adjustIeX_aux = 0;

// show tooltip functions

function showToolTip(tipDiv,lnk,xOffset,yOffset,msg) {
  var xCoor = xOffset + adjustIeX;
  findPos(tipDiv,lnk,xCoor,yOffset);
  showLayer(tipDiv);
  $(tipDiv).innerHTML = msg;
  showBubbleArrow(tipDiv,yOffset,"");
}

function showToolTipDelay(tipDiv,lnk,xOffset,yOffset,msg)
{
  ttPlm = window.setTimeout('showToolTip(\'' + tipDiv + '\',\'' + lnk + '\',' + xOffset + ',' + yOffset + ',\'' + msg + '\')', 1000);
}

function showAjaxToolTip(tipDiv,lnk,xOffset,yOffset) {
  if(!$(lnk)) // there's no anchor for the tooltip
    return;
  var arrowPos = (xOffset < 0)? "right" : "";
  findPos(tipDiv,lnk,xOffset,yOffset);
  showLayer(tipDiv);
  showBubbleArrow(tipDiv,yOffset,arrowPos);
}

function showAjaxToolTipDelay(tipDiv,lnk,xOffset,yOffset) {
  findPos(tipDiv,lnk,xOffset,yOffset);
  showLayer(tipDiv);
  showBubbleArrow(tipDiv,yOffset,"");
}

function showStickmanTip(url, lnk, xOffset, yOffset, timeout)
{
  if (!timeout) timeout = 1000;
	
  ttPlm = window.setTimeout(function() {
    new Ajax.Updater('toolTip', url, {
      asynchronous: true,
      evalScripts: true,
      onLoading: function(request) {
        showWaitIndicator(lnk);
      },
      onComplete: function(request) {
        hideWaitIndicator();
        showAjaxToolTipDelay('toolTip', lnk, (xOffset + adjustIeX_aux), yOffset);
      }
    });
  }, timeout);
}

function showNuggetTipDelay(tipDiv,lnk,xOffset,yOffset) {
  findPos(tipDiv,lnk,xOffset,yOffset);
  showLayer(tipDiv);
}

function showNuggetTip(url,lnk,xOffset,yOffset,fixedWidth) {
  hideToolTip('patient-tooltip');
    
  // calculate right edge and correct position to keep onscreen
  var p = $('patient-tooltip');
  var a = $(lnk);
  var xCorrection = 0;
  var xOverflow = fixedWidth + findPosX(a);
	
  if(xOverflow > document.body.offsetWidth)
    xCorrection = xOverflow - document.body.offsetWidth;

  ttPlm = window.setTimeout(function() {
    new Ajax.Updater('patient-tooltip', url, {
      asynchronous:true,
      evalScripts:true,
      onLoading: function(request) {
        showWaitIndicator(lnk);
      },
      onComplete: function(request) {
        hideWaitIndicator();
        showNuggetTipDelay('patient-tooltip', lnk, ((xOffset + adjustIeX_aux) - xCorrection), yOffset);
      }
    });
  }, 1000);
}

function showAreaToolTipDelay(tipDiv,lnk,imgMap,msg) {
  var map = findPosY($(imgMap));
  var mapX = findPosX($(imgMap));
  var s = $(tipDiv).style;
  var xy = $(lnk).coords;
  var coOrds = xy.split(",");
	
  // calculate right edge and correct position to keep onscreen
  var p = $(tipDiv);
  var xCorrection = 0;
  var xOverflow = p.offsetWidth + mapX + (coOrds[0]*1);
  var xPos = (((mapX*1) + (coOrds[0]*1) + adjustIeX) - (30 + xCorrection));
	
  if(msg) {
    $(tipDiv).innerHTML = msg;
  }
  if(xOverflow > document.body.offsetWidth) {
    xCorrection = xOverflow - document.body.offsetWidth;
    showBubbleArrow(tipDiv,10,"right");
  } else {
    showBubbleArrow(tipDiv,10,"");
  }

  s.left =  xPos + "px";
  s.top = (20 + (map*1) + (coOrds[1]*1)) + "px";
  // if tooltip appear off-left, set to 5px
  if(parseInt(s.left) < 0) {
    s.left = "5px";
  }
  showLayer(tipDiv);
}

// isolating tip code to work better with timeouts
function showAreaTip(url,lnk,imgMap) {
  hideToolTip('toolTip');
  ttPlm = window.setTimeout(function() {
    new Ajax.Updater('toolTip', url, {
      method: 'get',
      asynchronous:true,
      evalScripts:true,
      onLoading: function(request) {
        showWaitIndicator(lnk);
      },
      onComplete: function(request){
        hideWaitIndicator();
        showAreaToolTipDelay('toolTip', lnk, imgMap);
      }
    });
  }, 1000);
}
	
function hideToolTip(tipDiv) {
  hideLayer(tipDiv);
}

function clearOutToolTip() {
  window.clearTimeout(ttPlm);
//hideLayer('toolTip');     // removed to allow click on tip to dismiss
}

function delayCloseLayer(el,timeout) {
  if(!timeout)
    timeout = 2000;
  if($(el).style.visibility == 'visible')
    ttPlm = window.setTimeout('hideToolTip(\'' + el + '\')', timeout);
  else
    clearOutToolTip();
}

function delayCloseToolTip(timeout) {
  delayCloseLayer('toolTip',timeout);
}

function _showStickmanTip(link,id,xOffset,yOffset) {
  showStickmanTip(link,id,xOffset,yOffset);
  return false;
}

function initStickmanTip(selector,path,xOffset,yOffset) {
  var links = $$(selector);
  for(var i=0; i<links.length; i++) {
    links[i].onmouseover = function() {
      _showStickmanTip(path + this.rel, this.id, xOffset, yOffset);
    }
    links[i].onclick = function() {
      _showStickmanTip(path + this.rel, this.id, xOffset, yOffset);
    }
    links[i].onmouseout = function() {
      clearOutToolTip();
    }
    links[i].onblur = function() {
      clearOutToolTip();
    }
  }
}

//Added by JC to toggle DOM elements on/off
function toggleElement(element, enabled) {
  if(enabled){
    Element.show(element);
  }else{
    Element.hide(element);
  }
}

// swaps tabbed regions and changes look of selected tab
function swapTab(tab)
{
  hideDisplay("ui" + currTab);
  $("lnk" + currTab).className = "";
  $("lnk" + currTab).title = "";
  currTab = tab;
  showDisplay("ui" + tab);
  $("lnk" + currTab).className = "yah";
  $("lnk" + currTab).title = "You are here";
}

// migrate over to this to have multiple tab-strips per page
function swapMultipleTabs(tab)
{
  //  hideDisplay("ui" + currResults);
  $("lnk" + currResults).className = "";
  $("lnk" + currResults).title = "";
  currResults = tab;
  //   showDisplay("ui" + tab);
  $("lnk" + currResults).className = "yah";
  $("lnk" + currResults).title = "You are here";
}

function stripLeading(string,chr)
{
  var finished = false;
  for (var i = 0; i < string.length && !finished; i++)
    if (string.substring(i,i+1) != chr) finished = true;
  if (finished) return string.substring(i-1); else return string;
}

function stripTrailing(string,chr)
{
  var finished = false;
  for (var i = string.length - 1; i > -1 && !finished; i--)
    if (string.substring(i,i+1) != chr) finished = true;
  if (finished) return string.substring(0,i+2); else return string;
}

function stripLeadingTrailing(string,chr)
{
  return stripTrailing(stripLeading(string,chr),chr)
}

/************ help scripts ************/

var currHash = stripLeading(window.location.hash,"#");

// open up specified block
function openHelp(blk) {
  showDisplay(blk);
}

// close specified block
function closeHelp(blk) {
  hideDisplay(blk);
}

function toggleHelp(blk,parentBlk) {
  collapseAllHelp(parentBlk);
  if(currHash != "")
  {
    closeHelp(currHash);
    // reset YAH state of link
    restoreLink();
  }
  currHash = blk;
  openHelp(blk);
  // change YAH state of link
  setYahLink();
  // display show all link
  showInline("lnkShowAll");
  hideDisplay("lnkHideAll");
}

// set currently selected link
function setYahLink() {
  xbObj("lnk-" + currHash).className = "yah";
}

// restore currently selected link
function restoreLink() {
  xbObj("lnk-" + currHash).className = "";
}

// close all blocks
function collapseAllHelp(parentBlk) {
  var b = document.getElementById(parentBlk);
  var p = b.getElementsByTagName("div");
  for(var i=0; i<p.length; i++)
    if(p[i].className == "hlp")
      hideDisplay(p[i].id);
}

// open all blocks
function expandAllHelp(parentBlk) {
  var b = document.getElementById(parentBlk);
  var p = b.getElementsByTagName("div");
  for(var i=0; i<p.length; i++)
    if(p[i].className == "hlp")
      showDisplay(p[i].id);
}

function initHelp(parentBlk) {
  // open up specific block from URL hash, if present
  if(window.location.hash != "")
  {
    collapseAllHelp(parentBlk);
    openHelp(currHash);
    xbObj("lnk-" + currHash).className = "yah";
    hideDisplay("lnkHideAll");
  }
  else
  {
    // hide show all link
    hideDisplay("lnkHideAll");
    hideDisplay("lnkShowAll");
  }
}

// show inline element
function showInline(el) {
  xbStyleObj(el).display = "inline";
}

// generic swap text of link
function swapText(el,newMsg) {
  $(el).innerHTML = newMsg;
}

function toggleText(el,oldMsg,newMsg) {
  if(xbObj(el).innerHTML == oldMsg)
    swapText(el,newMsg);
  else
    swapText(el,oldMsg);
}

// toggle show/collapse all state
function toggleAllHelp(parentBlk,el,defaultMsg,newMsg) {
  if(xbObj(el).innerHTML == defaultMsg)
  {
    swapText(el,newMsg);
    expandAllHelp(parentBlk);
  }
  else
  {
    swapText(el,defaultMsg);
    collapseAllHelp(parentBlk);
  }
  // reset yah link
  xbObj("lnk-" + currHash).className = "";
}

// set cursor position of text field
function setCursorPosition(oInput,oStart,oEnd) {
  if(oInput.setSelectionRange )	// for mozilla
  {
    oInput.setSelectionRange(oStart,oEnd);
    // explicitly set focus to field
    oInput.focus();
  }
  else if(oInput.createTextRange)	// for IE
  {
    var range = oInput.createTextRange();
    range.collapse(true);
    range.moveEnd('character',oEnd);
    range.moveStart('character',oStart);
    range.select();
  }
}

function textCounter(field, countfield, maxlimit) {
  var value = $F(field);
  if (value.length > maxlimit) { // if too long...trim it!
    // TODO Instead of limiting text, disable form submit and add class to counter to indicate error (red font, for example)
    // Updating the value has unfortunate side-effect of moving cursor to beginning of field.
    $(field).value = value.substring(0, maxlimit);
  }
  // otherwise, update 'characters left' counter
  else {
    $(countfield).innerHTML = maxlimit - value.length;
  }	
}

function initLabelHover() {
  if(document.all) {
    var lab = $$('label')
    for(var i=0; i<lab.length; i++) {
      if(lab[i].getAttribute("htmlfor") != "") {
        lab[i].onmouseover = function() {
          this.style.textDecoration = "underline";
          this.style.cursor = "hand";
        }
        lab[i].onmouseout = function() {
          this.style.textDecoration = "none";
          this.style.cursor = "default";
        }
      }
    }
  }
}

function initButtonHover() {
  if(document.all && !window.opera) {
    var btn = $$('button');
    var btnspan = $$('button span');
    var b = document.getElementsByTagName("body").item(0);
    inp = b.getElementsByTagName("input");
    for(var i=0; i<inp.length; i++)	{
      if(inp[i].getAttribute("type") == "submit" && inp[i].className == 'btn')	{
        inp[i].onmouseover = function() {
          this.style.backgroundImage = "none";
        }
        inp[i].onmouseout = function() {
          this.style.backgroundImage = "url(/images/tiler_btn_face.gif)";
        }
      }
    }
    btn.each(function(button){
      button.onmouseover = function() {
        this.addClassName('button-on');
        this.firstChild.addClassName('button-span-on');
      }
      button.onmouseout = function() {
        this.removeClassName('button-on');
        this.firstChild.removeClassName('button-span-on');
      }
    });
  }
}

function setFocusField(fieldID) {
  $(fieldID).focus();
}

// sets equal height boxes
function makeEqualHeight(arr) {
  var box = arr; //list of DIV ids
  for(x=0;x<box.length;x++)
  { //determine the tallest div
    h = document.getElementById(box[x]).offsetHeight;
    for(y=0;y<box.length;y++)
    {
      test_h = document.getElementById(box[y]).offsetHeight;
      if(h<test_h) h = test_h;
    }
  }
  //set the height of all divs to the tallest
  for(x=0;x<box.length;x++)
    document.getElementById(box[x]).style.height = h +"px";
}

function makeRoundedBoxes() {
  PLM.init(function(){
    els = document.getElementsByClassName('corners')

    for (var i=0; i<els.length; i++) {
      el = els[i];
      new Insertion.Top(el, '<div class="cornert"><div></div></div>');
      new Insertion.Bottom(el, '<div class="cornerb"><div></div></div>');
    }
  });
}

function revealLabels(el) {
  tr = $(el);
  //tr.className = "row-hover";
  tr.addClassName("row-hover");
  lbls = tr.getElementsByTagName("label");
  for(var i=0; i<lbls.length; i++)
    lbls[i].style.visibility = "visible";
}

function hideLabels(el,rowClass) {
  tr = $(el);
  //tr.className = rowClass;
  tr.removeClassName("row-hover");
  lbls = tr.getElementsByTagName("label");
  for(var i=0; i<lbls.length; i++)
    lbls[i].style.visibility = "hidden";
}

function hideAllLabels(el) {
  tbl = $(el);
  if(tbl) {
    lbls = tbl.getElementsByTagName("label");
    for(var i=0; i<lbls.length; i++)
      lbls[i].style.visibility = "hidden";
  }
}

function initRadioLabels(selector) {
  var rows = $$(selector);

  for(var j=0; j<rows.length; j++) {
    rows[j].onmouseover = function() {
      revealLabels(this);
    }
    rows[j].onmouseout = function()  {
      hideLabels(this);
    }
    rows[j].onfocus = function()     {
      revealLabels(this);
    }
    rows[j].onblur = function()      {
      hideLabels(this)
    }

    if(document.all) {
      rows[j].onfocusin = function() {
        revealLabels(this);
      }
      rows[j].onfocusout = function() {
        hideLabels(this);
      }
    }
  }
}

function initRowHighlighting(selector) {
  var rows = $$(selector);

  for(var j=0; j<rows.length; j++) {
    rows[j].onmouseover = function() {
      this.addClassName('row-hover');
    }
    rows[j].onmouseout = function()  {
      this.removeClassName('row-hover');
    }
    rows[j].onfocus = function()     {
      this.addClassName('row-hover');
    }
    rows[j].onblur = function()      {
      this.removeClassName('row-hover');
    }

    if(document.all) {
      rows[j].onfocusin = function() {
        this.addClassName('row-hover');
      }
      rows[j].onfocusout = function() {
        this.removeClassName('row-hover');
      }
    }
  }
}

function enablePing() {
//alert("i have changed");
}

function linkTo(url) {
  window.location.href = url;
}

function showWaitIndicator(elem) {
  new Effect.Appear('swirl');
  if(elem) $(elem).style.cursor = 'progress';
}

function hideWaitIndicator(elem) {
  new Effect.Fade('swirl');
  if(elem) $(elem).style.cursor = null;
}


// TODO: Refactor into behavior/delegator.
function prepareInputsForHints() {
  // the types of elements that trigger display of hint
  var elementTypes = $w('input select a textarea');

  $$('span.hint').each(function(hintSpan) {
    elementTypes.each(function(elementType) {
      element = hintSpan.adjacent(elementType).first();
      if (element) _prepareElementForHint(element);
    });
  });
}

function _prepareElementForHint(element) {
  // Returns the first span with hint class that is adjacent to the
  // given element.
  function _hintSpan(element) {
    return $(element).adjacent('span.hint').first();
  }

  // unless this is a checkbox, on focus, show the hint
  if (element.type != "checkbox") {
    element.onfocus = function() {
      hintSpan = _hintSpan(this);
      hintSpan.style.display = "inline";
      showHintPointer(hintSpan);
    };
    element.onblur = function() {
      _hintSpan(this).style.display = "none";
    };
  }
  else {
    // checkbox handling
    element.onmouseover = function() {
      var hintSpan = _hintSpan(this);
      hintSpan.style.display = "inline";
      showHintPointer(hintSpan);
    };
    element.onmouseout = function() {
      _hintSpan(this).style.display = "none";
    };

    var label = element.adjacent('label').first();
    label.onmouseover = function() {
      var hintSpan = _hintSpan(this);
      hintSpan.style.display = "inline";
      showHintPointer(hintSpan);
    };
    label.onmouseout = function() {
      _hintSpan(this).style.display = "none";
    };
  }
}

// check if cookies are enabled
var cookieEnabled = (navigator.cookieEnabled) ? true : false;
if(typeof navigator.cookieEnabled == "undefined" && !cookieEnabled) { 
  document.cookie = "testcookie";
  cookieEnabled = (document.cookie.indexOf("testcookie") != -1) ? true : false;
}

function showProgress(el) {
  Element.show(el);
}

function hideProgress(el) {
  Element.hide(el);
}

function cycleTabs(section, currentTab) {
  // Unselect all tabs
  $(section).select('li').each(function (tab) {
  	tab.removeClassName("yah");
  });
	  // Select current tab
  $(currentTab).addClassName("yah");
}

function initToolTips() {	
  var asstdToolTips = new Array($('toolTip'), $('patient-tooltip'), $('disease-switcher'), $('mnu-resizer'), $('nav-public'));
  asstdToolTips.each(function(tips) {
    if(tips) {
      tips.onmouseover = function() {
        clearOutToolTip();
      }
      tips.onmouseout = function() {
        delayCloseLayer(this.id);
      }
    }
  });
}

function backToTop() {
  var b = $("back-to-top");
  if(b) {
    window.onscroll = function() {
      b.style.visibility = "visible";
    }
  }
}

function browserUpgradeAdvisory() {
  if((document.all && !window.XMLHttpRequest) && !window.opera) {
    if($('ajax-messages')) {
      msg = 'The web browser you are using is not optimized for this site. Please consider upgrading. <a href="/help/faq/General%20Questions#browser">Learn more</a>';
      new Insertion.After('ajax-messages', '<div class="notification warning">' + msg + '</div>');
    }
  }
}

// this attempts to right a usability wrong by passing focus to the first item in
// an absolutely positioned menu
function showMenuBox(el) {
  var mnu = $(el);
  mnu.style.visibility = 'visible';
}

function initSwitcher(menuId, linkId) {
  var mnu = $(menuId);
  var lnk = $(linkId);
  if (mnu){
    mnu.absolutize();
  }
  if(lnk) {
      lnk.onclick = function() {
          if (mnu.style.visibility == 'hidden') {
              var yOffset = lnk.offsetHeight - 1;
              mnu.clonePosition(lnk,{setWidth: false, setHeight: false, offsetTop: yOffset});
              showMenuBox(mnu);  //$(mnu).style.visibility = 'visible';
              toggleSelectBoxes('hidden', mnu);
          }
          else {
              mnu.style.visibility = 'hidden';
              toggleSelectBoxes('visible', mnu);
          }
          return false;
      }
      mnu.onmouseout = function() {
        delayCloseLayer(menuId);
      }
      mnu.onmouseover = function() {
        clearOutToolTip();
      }

  }
}

function initCommunitySwitcher() {
  var mnu = 'nav-public';
  var lnk = 'community-switcher';
  if($(lnk)) {
    $(lnk).onclick = function() {
      if ($(mnu).style.visibility == 'hidden') {
        var yOffset = $(lnk).offsetHeight - 1;
        findPos(mnu,lnk,0,yOffset);
        showMenuBox(mnu);  //$(mnu).style.visibility = 'visible';
        toggleSelectBoxes('hidden', mnu);
      //alert(Element.modelId(mnu));
      }
      else {
        $(mnu).style.visibility = 'hidden';
        toggleSelectBoxes('visible', mnu);
      }
      return false;
    }
    $(lnk).onmouseout = function() {
      delayCloseLayer(mnu);
    }
    $(lnk).onmouseout = function() {
      delayCloseLayer(mnu);
    }
  }
}

function initTextResizerLink() {
  var resizer = $$('#lnk-resizer');
  if(resizer.length > 0) {
    resizer.first().observe('click', function(e) {
      findPos('mnu-resizer', this.id, 0, 16);
      toggleVisibility('mnu-resizer');
      e.stop();
    });
  }
}

var textSizeOnLoad = null;

function pageInit(textSize) {
  initLabelHover();
  initButtonHover();
  if (textSize) selectStyleSheet(textSize);
  initTextResizerLink();
  initToolTips();
  backToTop();
  initCommunitySwitcher();
  Event.addBehavior({'#fld-main-search': Behaviors.Form.HintedTextBox,
                     '.btn-array': Behaviors.UI.NoDoubleClick});
  // Background tasks (that don't hold up page load)
  setTimeout(function() {
    linkAcronymsToHelp();
    // Regex in this function is *very* expensive, skipping until/when we optimize it.
    // preloadCssImages();
  }, 0);
}

/**
 * Scan the page for acronyms and turn them into help links.
 */
function linkAcronymsToHelp() {
  // Link acronyms to FAQ/Glossary terms
  $$('acronym').each(function(acronym) {
    linkToHelp(acronym);
  });
}

function linkToHelp(element) {
  var helpName = element.title ? element.title : element.innerHTML;

  // Assign popup help behavior to element
  element.onclick = function() {
    showHelp(this, helpName);
  };
  element.onmouseover = function() {
    showHelp(this, helpName);
  };
  element.onmouseout = function() {
    clearOutToolTip();
  };
}

function showHelp(element, helpName) {
  var ROOT_URL = '/help/show/';
  var X_OFFSET = 0;
  var Y_OFFSET = 50;

  var url = ROOT_URL + helpName;
  showStickmanTip(url, $(element), X_OFFSET, Y_OFFSET, 0);
}

function selectStyleSheet(textSize) {
  var i, a;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
    if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title")) {
      a.disabled = true;
      if(a.getAttribute("title") == textSize + '%') a.disabled = false;
    }
  }
  // set YAH state for resizer menu
  setTextSizerYahState(textSize);  
  textSizeOnLoad = textSize;
}

function setTextSizerYahState(textSize) {
  if($('mnu-resizer')) {
    $('mnu-resizer').select('a.yah').invoke('removeClassName', 'yah');
    $('txt-' + textSize).addClassName('yah');
  }
}

function changeTextSize(textSize) {
  hideLayer('mnu-resizer');
  selectStyleSheet(textSize);
  saveTextSizePreference(textSize, true);
}

function getActiveStyleSheet() {
  if ($$('link[rel="alternate stylesheet"]').size() == 0)
    return null;
    
  var i, a;
  for(i=0; (a = document.getElementsByTagName("link")[i]); i++) {
    if(a.getAttribute("rel").indexOf("style") != -1 && a.getAttribute("title") && !a.disabled) 
      return parseInt(a.getAttribute("title"));
  }
  return 100;
}

window.onbeforeunload = function() {
  textSize = getActiveStyleSheet();
  if (textSize != textSizeOnLoad) {
    saveTextSizePreference(textSize, false);
  }
};

function saveTextSizePreference(textSize, asynchronous) {
  url = '/account/text_size/' + textSize;
  new Ajax.Request(url, {method: 'post', asynchronous: asynchronous});
}



function createCookie(name,value,days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else expires = "";
  document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(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;
}


/**
 * Prototype helper, this is a substitute for using new Element(). Got this from:
 * http://www.sergiopereira.com/articles/prototype.js.html#Element.Methods
 * 
 * @param {String} tagName
 * @param {Object} attributes
 * @param {Object} styles
 */
var $CE = function(tagName, attributes, styles) { 
  el = new Element(tagName, attributes);
  // Additional convenience to set styles, not in Prototype
  if (styles) {
    $H(styles).each(function(pair) {
      el.style[pair.key] = pair.value;
    });
  }
	
  return $(el);
};

/**
 * Returns the value of the selected radio button in the radio group, null if
 * none are selected, and false if the button group doesn't exist. We need this
 * because Prototype's $F method does not work for radio buttons.
 *
 * @param {radio Object} or {radio id} el
 * OR
 * @param {form Object} or {form id} el
 * @param {radio group name} radioGroup
 * 
 * Found this in a blog post by Aaron D. Campbell at:
 * http://xavisys.com/using-prototype-javascript-to-get-the-value-of-a-radio-group/
 * Thanks, dude!
 */
function $RF(el, radioGroup) {
  if ($(el).type && $(el).type.toLowerCase() == 'radio') {
    var radioGroup = $(el).name;
    var el = $(el).form;
  }
  else if ($(el).tagName.toLowerCase() != 'form') {
    return false;
  }

  var checked = $(el).getInputs('radio', radioGroup).find(
    function(re) {
      return re.checked;
    }
    );

  return checked ? $F(checked) : null;
}
/*
 * Extensions to Prototype's Element, courtesy of:
 * http://www.sergiopereira.com/articles/prototype.js.html#Element.Methods
 */
Element.addMethods({
  //removes any child noes from the element
  //example: <div id="myDiv"><b>hello</b></div>
  //         $('myDiv').clearChildren();
  //     ==> <div id="myDiv"></div>
  clearChildren: function(element) {
    element = $(element);
    $A(element.childNodes).each(function(e){
      e.parentNode.removeChild(e);
    });
    return element;
  },
  //method that creates a new element and appends to the current element
  // example: <div id="myDiv">Please</div>
  //          $('myDiv').append('A',{href:'otherpage.html', className:'red'}).update('Continue...');
  //     ==>  <div id="myDiv">Please<a href="otherpage.html" class="red">Continue...</a></div>
  append: function(element, tagName, attributes, styles) {
    element = $(element);
    var newEl = $CE(tagName, attributes, styles);
    element.appendChild(newEl);
    return newEl;//<-- this one returns the new element
  },
  getValueOfRadioGroup: function(element) {    
    return $$("input:checked[name='"+element.name+"']").pluck('value').first();
  },
  //appends a text node to the element
  // example: <div id="myDiv"><b>hello</b></div>
  //          $('myDiv').appendText(', John');
  //      ==> <div id="myDiv"><b>hello</b>, John</div>
  appendText: function(element, text) {
    element = $(element);
    var t = document.createTextNode(text);
    element.appendChild(t);
    return element;
  }
});

/*
 * Global handling for Ajax requests.
 */
Ajax.Responders.register({
  onComplete: function(request, response) {
    if (!request.success()) {
      if (PLM.Ajax.sessionExpired(response)) {
        // Handle expired session - reload page to force redirect to login
        alert("For security purposes, you were logged out due to inactivity. Click OK to log in, and we'll return you to this page.");
        location.reload();
      }
      else if (request.status >= 500) {
        PLM.errorAlert(); // Standard ajax error handling
      }
      else {
        // Do nothing. Validation errors and other responses are assumed to be handled (or not handled) ad hoc.
      }
    }
  }
});


/*
 * Functions for disabling and [re-]enabling links. 
 * Useful for temporary disabling of links during in-place ajax operations.
 */

function disableLink(link) {
  link = $(link);
  link._onclick = link.onclick;
  link.onclick = function() {
    return false;
  }
}

// Restores link functionality (if previously disabled)
function enableLink(link) {
  link = $(link);
  if (link._onclick) {
    link.onclick = link._onclick;
    delete link._onclick;
  }
}


function scrollToAnchor() {
  if(!window.opera) {
    $$('a[href^=#]:not([href=#])').each(function(element) {
      element.observe('click', function(event) {
        new Effect.ScrollTo(this.hash.substr(1));
        if(document.all)
          Event.stop(event);  // removed to retain anchor hash in URL
      }.bindAsEventListener(element))
    })
  }
}


/*
 * Scroll the page vertically just enough to fit the element that may be hanging off the bottom of the screen
 * pass true as the second argument to have this called in a timeout so that the calculations on the element can be called after layout
 */
function scrollToShowWholeElement(element)
{
  if (!element) return;
  var inTimeout = false;
  var args = $A(arguments);
  if (args.length == 2) {
    inTimeout = args.last();
  }
  if (inTimeout) {
    setTimeout(function(){
      scrollToShowWholeElement(element, false);
    }, 50);
    return;
  }
  else{
    element = Object.isString(element) ? $(element) : element;
    var elementHeight = element.getHeight();
    var screenHeight = document.viewport.getHeight();
    var elemScreenYPos = element.viewportOffset()[1];
    var needToScroll = elementHeight - ( screenHeight - elemScreenYPos);
    if (needToScroll > 0 && elemScreenYPos > 0){
      var scrollPos = document.viewport.getScrollOffsets().top;
      new Effect.Tween(null,scrollPos,scrollPos+needToScroll,{},function(n) {
        window.scrollTo(0,n);
      });
    }
  }
    
}


function togglePanel(panel,link,newText) {
  var effect = (document.all && !window.opera) ? 'appear' : 'blind';
  if(!newText)
    newText = 'Show';
  new Effect.toggle($(panel),effect);
  plmToggleClassName(link,'expanded','collapsed');
  toggleText(link,'Hide',newText);
}

function showWait(sourceEl, xOffset, yOffset) {
  xOffset = (typeof xOffset == 'undefined') ? 0 : xOffset;
  yOffset = (typeof yOffset  == 'undefined') ? 25 : yOffset;
  //	findPos('swirl', sourceEl, xOffset, yOffset);
  //	new Effect.Appear('swirl');
  showWaitIndicator(sourceEl);
}

function hideWait() {
  //	new Effect.Fade('swirl');
  hideWaitIndicator();
}

function toggle_user(id){
  var link = $$('#user-'+ id +' th a')[0];
  var nextRow =  $$('#user-'+ id +' + tr.patient-detail')[0];
  if(link.className=='minus'){
    link.className = '';
    if (nextRow) {
      $$('#user-'+ id +' + tr.patient-detail .nugget-wrap').invoke('setStyle',{
        display: 'none'
      });
      nextRow.style.display = 'none';
    }
  } else {
    link.className = 'minus';
    link.onclick = function(e) {
      toggle_user(id); Event.stop(e); return false;
    };
    if (nextRow) {
      nextRow.style.display = '';
      $$('#user-'+ id +' + tr.patient-detail .nugget-wrap').invoke('setStyle',{
        display: 'block'
      });
    }
  }
  return false;
}

/* Sets hidden field and submits form. */
function submitWithCommand(link, command) {
  $('submit_command').value = command;
  $(link).up('form').submit();
}

/* Unchecks radio buttons or checkboxes. */
function uncheckAll(selector) {
  $$(selector).each(function(e) { 
    e.checked = false;
  });
}

/*
	Shortlinks
	constrains the length of links displayed to a defined length
	written by Chris Heilmann (http://icant.co.uk/)
*/
function shortlinks(urlLength)
{
  // defines where the link should be cut off, from the right or the middle
  var mode='right';
  // the maximum length of the links
  if(urlLength == undefined)
    var mustlength = 65;
  else
    var mustlength = urlLength;
  // the string added to or in the middle of the link text after shortening
  var connector='...';
  // the title added to the link, %url% will be replaced with the real link
  var titleadd=' (This link is shortened. The full address: %url%)';
  // the links to be shortened
  var contentlinks=document.getElementsByTagName('a');

  // loop over all links
  for(var i=0;i<contentlinks.length;i++)
  {
    // check if the link has an href attribute and content
    if(!contentlinks[i].getAttribute('href') || !contentlinks[i].firstChild){
      continue;
    }
    // check if the link starts with http: and that it is longer than the allowed length
    // CN: modified to check for https
    var t=contentlinks[i].firstChild.nodeValue;
    //if(/http:/.test(t) && t.length>mustlength)
    if(/http/.test(t) && t.length>mustlength)
    {
      // get the text of the link
      // shorten accordingly and add the separator string
      switch(mode){
        case 'middle':
          var newt=t.substr(0,mustlength/2)+connector+t.substr(t.length-mustlength/2-connector.length,t.length);
          break;
        case 'right':
          var newt=t.substr(0,mustlength-connector.length)+connector;
          break;
      }
      // set the title, and replace the original link text
      contentlinks[i].title+=titleadd.replace(/%url%/,t);
      contentlinks[i].replaceChild(document.createTextNode(newt),contentlinks[i].firstChild);
    }
	
  }
}

/**
 * --------------------------------------------------------------------
 * jQuery-Plugin "preloadCssImages"
 * by Scott Jehl, scott@filamentgroup.com
 * http://www.filamentgroup.com
 * reference article: http://www.filamentgroup.com/lab/automated_image_preloading/
 * demo page: http://www.filamentgroup.com/examples/preloadImages/
 * 
 * Copyright (c) 2008 Filament Group, Inc
 * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
 *
 * Version: 1.0, 31.05.2007
 * Changelog:
 * 	02.20.2008 initial Version 1.0
 *  03.25.2008 modified by PatientsLikeMe to use Prototype JS Library
 * --------------------------------------------------------------------
 */
preloadCssImages = function(){
  //dump all the css rules into one string
  var sheets = document.styleSheets;
  var cssPile = '';
  for(var i = 0; i<sheets.length; i++){
    if(!document.all && !window.opera){
      var thisSheetRules = document.styleSheets[i].cssRules;
      for(var j = 0; j<thisSheetRules.length; j++){
        cssPile+= thisSheetRules[j].cssText;
      }
    }
    else {
      cssPile+= document.styleSheets[i].cssText;
    }
  }
	
  //parse string for image urls and load them into the DOM
  var allImgs = [];//new array for all the image urls
  var imgUrls = cssPile.match(/[^\/]+\.(gif|jpg|jpeg|png)/g);//reg ex to get a string of between a "/" and a ".filename"
  if(imgUrls != null && imgUrls.length>0 && imgUrls != ''){//loop array
    var arr = imgUrls.toArray();	//create array from regex obj
    arr.each(function(imgPath){
      var img = new Image();
      img.src = '/images/'+ imgPath;
      allImgs.push(img);
    });
  }
	
  return allImgs;
}
String.prototype.trim = function() {
  return this.replace(/^\s+|\s+$/g,"");
}

var PLM_TINYMCE_CONFIG = $H({
  theme : "advanced",
  convert_urls : false,
  force_p_newlines : true,
  auto_cleanup_word : true,  
  paste_auto_cleanup_on_paste : true,
  paste_remove_styles : true,
  paste_remove_spans : true,
  trim_span_elements : true,
  invalid_elements : "span",
  cleanup_on_startup : true,
  onchange_callback : "enablePing",
  content_css : "/stylesheets/plm_custom_tinymce.css",
  plugins : "emotions,paste,plmimage,tabjump,safari",
  theme_advanced_layout_manager : "SimpleLayout",
  theme_advanced_toolbar_location : "bottom",
  theme_advanced_toolbar_align : "right",
  theme_advanced_buttons1 : "bold,italic,link,plmImage,emotions,separator,pasteword",
  theme_advanced_buttons2 : "",
  theme_advanced_buttons3 : "",
  theme_advanced_resizing_min_width : 400,
  theme_advanced_resizing_max_width : 800
});

