﻿/**

    kmw_firstvoices.js
    
    FirstVoices integration of KeymanWeb user interface.  Shows a keyboard selection button and an On Screen Keyboard toggle button next to the active edit control
    
    Usage: include this file in the HEAD section:  <script type='text/javascript' src='.../kmw_firstvoices.js'></script>
*/

/*
    User-definable options.  Change these options to change the default behaviour of KeymanWeb when a page loads
*/
var 
    kmw_showosk = false,            // Show on screen keyboard automatically when page loads
    kmw_activebydefault = false,    // Make the first KeymanWeb keyboard loaded active by default when the page loads
    kmw_usecookie = true;           // Use cookies to remember the last keyboard selected and whether the page is loaded by default, for current domain
/*
    End of User-definable options
*/

var
    kmw_shim = null,
    kmw_control = null,
    kmw_controller = null, 
    kmw_osk = null, 
    kmw_kbdon = null, 
    kmw_controller_hovered = false,
    kmw_keyboards = new Array(),
    kmw_lastactivekeyboard = -1;

/* Update the KeymanWeb user interface when switching controls */
function kmw_dofocus(someElement,focusing){
  if(window.event) someElement=window.event.srcElement;
  kmw_control = someElement;
  if(focusing)
    kmw_controller.style.display = 'block';
  else if(!(KeymanWeb.UIState()&1) && !kmw_controller_hovered)
    kmw_controller.style.display = 'none';
  kmw_controller.style.left = (KeymanWeb.GetAbsoluteX(someElement)) + 'px';
  kmw_controller.style.top = (KeymanWeb.GetAbsoluteY(someElement) + someElement.offsetHeight + 2) + 'px';
  
  if(kmw_showosk && KeymanWeb.GetActiveKeyboard() != '' && focusing)
    /*if(KeymanWeb.HelpIsPinned()) KeymanWeb.ShowPinnedHelp();
    else */kmw_showhelp();
  else if(!(KeymanWeb.UIState()&1))
    KeymanWeb.HideHelp();
}

/* Show the on screen keyboard (x,y params are function signature when called via KeymanWeb.onshowhelp) */
function kmw_showhelp(x,y)
{
  if(KeymanWeb.HelpIsPinned()) KeymanWeb.ShowHelp(-1,-1);
  else
  {
    kmw_controller.style.display = 'block';
    KeymanWeb.ShowHelp(kmw_controller.offsetLeft, kmw_controller.offsetTop + kmw_controller.offsetHeight);
  }
}

/* Hide the on screen keyboard */
function kmw_hidehelp()
{
  kmw_showosk = false;
  kmw_osk.setSelected(false);
  KeymanWeb.FocusLastActiveElement();
}

/* When a keyboard is dynamically loaded, show the on screen keyboard if it should be visible - called by KeymanWeb.onkeyboardloaded */
function kmw_kbdloaded()
{
  if(kmw_showosk && kmw_controller && kmw_controller.style.display == 'block') kmw_showhelp();
  kmw_updatemenu();
  kmw_updatecookie();
}

/* Toggle the on screen keyboard display - KMW button control event */
function kmw_switchosk()
{
  kmw_showosk = !kmw_showosk;
  kmw_osk.setSelected(kmw_showosk);
  KeymanWeb.FocusLastActiveElement();
  kmw_updatecookie();
}

/* Toggle the active keyboard - KMW button control event */
function kmw_switchkbd_single()
{
  var v = KeymanWeb.GetActiveKeyboard() == '';
  if(v)
  {
    if(kmw_keyboards.length == 0) return;
    if(kmw_lastactivekeyboard < kmw_keyboards.length && kmw_lastactivekeyboard >= 0)
    {
      KeymanWeb.SetActiveKeyboard(kmw_keyboards[kmw_lastactivekeyboard].InternalName);
    }
    else
    {
      KeymanWeb.SetActiveKeyboard(kmw_keyboards[0].InternalName);
      kmw_lastactivekeyboard = 0;
    }
  }
  else
  {
    KeymanWeb.SetActiveKeyboard('');
  }
  if(kmw_kbdon) kmw_kbdon.setSelected(v);
  KeymanWeb.FocusLastActiveElement();
  kmw_updatemenu();
  kmw_updatecookie();
}

/* Toggle the active keyboard - KMW button control event */
function kmw_switchkbd_next()
{
  var v = KeymanWeb.GetActiveKeyboard() == '';
  if(v)
  {
    if(kmw_keyboards.length == 0) return;
    KeymanWeb.SetActiveKeyboard(kmw_keyboards[0].InternalName);
    kmw_lastactivekeyboard = 0;
  }
  else
  {
    if(kmw_lastactivekeyboard == kmw_keyboards.length-1)
    {
      KeymanWeb.SetActiveKeyboard('');
      v = false;
    }
    else
    {
      KeymanWeb.SetActiveKeyboard(kmw_keyboards[++kmw_lastactivekeyboard].InternalName);
      v = true;
    }
  }
  if(kmw_kbdon) kmw_kbdon.setSelected(v);
  KeymanWeb.FocusLastActiveElement();
  kmw_updatemenu();
  kmw_updatecookie();
}

/* kmw_button object - object for the KeymanWeb buttons */
kmw_button = function(src, caption, selected)
{
  this.onclick = null;
  this.onmouseover = null;
  this.onmouseout = null;
  this._elem = null;
  this._down = false;
  this._over = false;
  this._selected = selected;
  
  /*public*/ this.getElem = function()
  {
    return this._owningObject._elem;
  };
  
  /*private*/ this._updatestyle = function()
  {
    with(this._owningObject._elem.style) {
      if(this._owningObject._over)
      {
        background = '#dfb4b4';
        margin = '0px';
        if(this._owningObject._selected) {
          border = 'solid 1px #ad4a28';
        }
        else {
          border = 'solid 1px #dfb4b4';
        }
      }
      else if(this._owningObject._selected)
      {
        background = '#f3e5de';
        margin = '0px';
        border = 'solid 1px #ad4a28';
      }
      else
      {
        background = 'none';
        margin = '0px';
        border = 'solid 1px white';
      }
    }
  };
  
  /*private*/ this._mouseover = function()
  {
    kmw_controller_hovered = true;
    this._owningObject._over = true;
    if(this._owningObject.onmouseover != null) this._owningObject.onmouseover();
    this._owningObject._updatestyle();
  };
  
  /*private*/ this._mouseout = function()
  {
    kmw_controller_hovered = false;
    this._owningObject._over = false;
    if(this._owningObject.onmouseout != null) this._owningObject.onmouseout();
    this._owningObject._updatestyle();
  };
  
  /*private*/ this._click = function()
  {
    //alert(this._owningObject.onclick);
    //if(this._owningObject.onclick != null) 
    if(this._owningObject.onclick != null) 
        return this._owningObject.onclick();
    return false;
  };

  /*private*/ this._mousedown = function()
  {
    this._owningObject._down = true;
    this._owningObject._updatestyle();
  };
  
  /*private*/ this._mouseup = function()
  {
    this._owningObject._down = false;
    this._owningObject._updatestyle();
  };
  
  /*public*/ this.setSelected = function(value)
  {
    this._owningObject._selected = value;
    this._owningObject._updatestyle();
  };
  
  /*public*/ this.getSelected = function()
  {
    return this._owningObject._selected;
  };

  /*public*/ this.getOver = function()
  {
    return this._owningObject._over;
  };
  
  /*public*/ this.getDown = function()
  {
    return this._owningObject._down;
  };

  this._owningObject = this; // simplifies meaning of 'this'
  
  var elemImg = document.createElement('img');
  this._elem = document.createElement('div');
  this._elem._owningObject = this;
  elemImg.style.display = 'block';
  elemImg.src = KeymanWeb_Root + src;
  with(this._elem.style) {
    margin = '0px'; //display = 'inline';
    width = '24px';
    height = '24px';
    zIndex = '999';
    lineHeight = '100%';
    styleFloat = cssFloat = 'left';
  }
  elemImg.title = caption;
  elemImg.alt = caption;
  this._elem.appendChild(elemImg);
  this._elem.onmouseover = this._mouseover;
  this._elem.onmouseout = this._mouseout;
  this._elem.onmousedown = this._mousedown;
  this._elem.onmouseup = this._mouseup;
  elemImg._owningObject = this;
  elemImg.onclick = this._click;
  
  this._updatestyle();
};

function kmw_addevent(elem, evt, func)
{
  if(elem.addEventListener) elem.addEventListener(evt,func,false);
  else elem.attachEvent('on'+evt,func);
}

function kmw_shouldattach(elem)
{
	if(typeof(KeymanWeb_AttachType) != 'undefined' && KeymanWeb_AttachType == 'manual') 
	  return typeof(elem.attributes['kmw_enable']) != 'undefined' && elem.attributes['kmw_enable'].value == '1';
	  
	return !elem.attributes['kmw_disable'] || elem.attributes['kmw_disable'].value != '1';
}

function kmw_attach(elem)
{
    KeymanWeb.AttachToControl(elem);
    kmw_addevent(elem, 'focus', function() { kmw_dofocus(this,1); });
    kmw_addevent(elem, 'blur', function() { kmw_dofocus(this,0); });
    kmw_addevent(elem, 'click', function() { kmw_dofocus(this,1); });
}
    
/* Initialize KeymanWeb controls and set defaults, called when page loads */
function kmw_init() {
	//when the page loads, set the last textarea name to "" so its not null
	KeymanWeb.Init();
	KeymanWeb.SetMode('manual');
	KeymanWeb.onshowhelp = kmw_showhelp;
	KeymanWeb.onoskhidehelp = kmw_hidehelp;
	KeymanWeb.onkeyboardloaded = kmw_kbdloaded;

	var kbds=KeymanWeb.GetKeyboards();

    if(!kmw_usecookie && kmw_activebydefault) kmw_switchkbd_single(); //KeymanWeb.SetActiveKeyboard('Keyboard_ktunaxa3_kmw');

	kmw_controller = document.createElement('div');

	kmw_kbdon = new kmw_button(kbds.length > 1 ? 'kmw_logo_16_down.gif' : 'kmw_logo_16.gif', 'Use Web Keyboard', kmw_activebydefault); 
	kmw_controller.appendChild(kmw_kbdon.getElem());

	kmw_osk = new kmw_button('kmw_osk_16.gif', 'Show On Screen Keyboard', kmw_showosk); 
	kmw_osk.onclick = kmw_switchosk;
	kmw_controller.appendChild(kmw_osk.getElem());
	
	kmw_controller.style.display = 'none';
	kmw_controller.style.zIndex = '998';
	kmw_controller.style.position = 'absolute';
	
	document.body.appendChild(kmw_controller);
	
	var elems = document.getElementsByTagName('input');
	for(var i = 0; i < elems.length; i++)
	{
	    if(elems[i].type.toLowerCase() == 'text')
	    {
        if(kmw_shouldattach(elems[i]))
    	    kmw_attach(elems[i]);
      }
	}
	elems = document.getElementsByTagName('textarea');
	for(var i = 0; i < elems.length; i++)
	{
      if(kmw_shouldattach(elems[i]))
    	  kmw_attach(elems[i]);
	}

	elems = document.getElementsByTagName('iframe');
	for(var i = 0; i < elems.length; i++)
	{
      if(kmw_shouldattach(elems[i]))
    	  kmw_attach(elems[i]);
	}
	
	// Check the number of installed keyboards to determine whether or not we will have a dropdown
	if(kbds.length > 1)
	{
	    // Multiple keyboards
	    kmw_kbdon.getElem().id = 'kmwico';
	    kmw_kbdon.getElem().style.width = '36px';
	    kmw_kbdon.onmouseover = function()
        {
            KeymanWeb_KbdList.className="sfhover";
            if(kmw_shim)
              with (kmw_shim.style)
              {
                left = KeymanWeb_KbdList.style.left;
                top = KeymanWeb_KbdList.style.top;
                width = KeymanWeb_KbdList.offsetWidth+"px";
                height = KeymanWeb_KbdList.offsetHeight+"px";
                zindex = KeymanWeb_KbdList.style.zIndex-1;
                display = 'block';
              }
        };
	    kmw_kbdon.onmouseout = function()
        {
            KeymanWeb_KbdList.className="sfunhover";
            if(kmw_shim) kmw_shim.style.display = 'none';
        };
	    kmw_kbdon.onclick = null;
	    kmw_createmenu();
	}
	else if(kbds.length > 0)
  {
    kmw_keyboards.push({InternalName: kbds[0].InternalName, Index: 0});
    kmw_kbdon.onclick = kmw_switchkbd_single;
	}
    kmw_loadcookie();
}

if(window.addEventListener) window.addEventListener('load',kmw_init,false);
else window.attachEvent('onload',kmw_init);

/* ----------------------------------------
   Drop down menu
   ---------------------------------------- */

var KeymanWeb_DefaultKeyboardHelp='<span style="font-size:7.5pt">KeymanWeb is not running.  Choose a keyboard from the list</span>';
var KeymanWeb_KbdList, KMWSel;

/* Select a keyboard from the drop down menu */
function kmw_switchkbd(kbd,refocus)
{
    var name, index;
    if(kbd < 0) { name = ''; index = ''; }
    else { name = kmw_keyboards[kbd].InternalName; index = kmw_keyboards[kbd].Index; }
    
    KeymanWeb.SetActiveKeyboard(name);
    if(refocus) KeymanWeb.FocusLastActiveElement();
    kmw_kbdon.setSelected(name != '');
    
    if(kbd >= 0) kmw_lastactivekeyboard = kbd;

    kmw_updatemenu();
    kmw_updatecookie();
};

function kmw_updatemenu()
{
  var k = null;
  if(KeymanWeb.GetActiveKeyboard() == '' || kmw_lastactivekeyboard < 0)
    k=document.getElementById('KMWSel_$');
  else
    k=document.getElementById('KMWSel_'+kmw_keyboards[kmw_lastactivekeyboard].InternalName+'$'+kmw_keyboards[kmw_lastactivekeyboard].Index);
  if(k)
  {
    if(KMWSel!=null) KMWSel.className='';
    k.className='selected'; KMWSel=k;
  }
}

document.writeln(
    "<style type='text/css'>"+
    "        #KeymanWeb_KbdList {"+
    "           display: block;"+
    "        	position: absolute;"+
    "	        width: 200px;"+
    "           line-height: 100%;"+
    "           margin: 0; "+
    "           clear: both; float: none; top: auto;"+
    "	        border: solid 1px #ad4a28;"+
    "           list-style: none;"+
    "           padding: 0;"+
    "	        background: white;"+
    "         max-height: 200px; overflow-y: scroll; overflow-x: hidden; white-space: nowrap;"+
    "	        z-index: 1000; /* above the osk */"+
    "        }"+
    "        * html #KeymanWeb_KbdList { height: expression(this.scrollHeight > 199 ? '200px' : 'auto'); }"+
    "        .sfunhover#KeymanWeb_KbdList {"+
    "            display: none; left: -999px;"+
    "            }"+
    "        .sfhover#KeymanWeb_KbdList {"+
    "           display: block;"+
    "           left: auto;"+
    "       }"+
    "        #KeymanWeb_KbdList li { float: none; width: auto; padding: 0; margin: 0;}"+
    "        #KeymanWeb_KbdList li a {"+
    "	        display: block; "+
    "	        padding: 2px 4px;"+
    "	        font-size: 7.5pt;"+
    "          text-decoration: none;"+
    "        }"+
    "        #KeymanWeb_KbdList li a.selected {"+
    "	        font-weight: bold;"+
    "        }"+
    "        #KeymanWeb_KbdList li a:hover {"+
    "	        color: white;"+
    "	        background-color: #ad4a28;"+
    "          text-decoration: underline;"+
    "        }"+
    "        #KMW_Keyboard { border-bottom: solid 1px #ad4a28; }"+
    "</style>");

/* Create the drop down menu and populate with loaded KeymanWeb keyboards */
function kmw_createmenu()
{
    if (window.createPopup && !window.XmlHttpRequest)
    {
      kmw_shim = document.createElement('iframe');
      with(kmw_shim)
      {
        src = '';
        style.display = 'none';
        style.position = 'absolute';
        style.filter = 'progidXImageTransform.Microsoft.Alpha(style=0,opacity=0)';
        frameBorder = '0';
        scrolling = 'no';
      }
      kmw_kbdon.getElem().appendChild(kmw_shim);
    }
    
    KeymanWeb_KbdList=document.createElement('ul');
    KeymanWeb_KbdList.id='KeymanWeb_KbdList';
    KeymanWeb_KbdList.className='sfunhover';
    var elems=document.getElementsByTagName('div');

    var li=document.createElement('li');
    var a=document.createElement('a');
    a.innerHTML='English';
    a.href="javascript:kmw_switchkbd(-1,true);";
    a.id='KMWSel_$';
    a.className='selected';
    li.appendChild(a);
    KMWSel=a;
    KeymanWeb_KbdList.appendChild(li);
    
    var kbds=KeymanWeb.GetKeyboards(), added=[];
    for(var kbd in kbds)
    {
        var li=document.createElement('li');
        var a=document.createElement('a');
        a.innerHTML=kbds[kbd].Name;
        if(!added[kbds[kbd].InternalName]) added[kbds[kbd].InternalName]=0;
        added[kbds[kbd].InternalName]++;

        var n=added[kbds[kbd].InternalName];
        kmw_keyboards.push({InternalName: kbds[kbd].InternalName, Index: n});

        a.href="javascript:kmw_switchkbd("+(kmw_keyboards.length-1)+", true);";
        a.id='KMWSel_'+kbds[kbd].InternalName+'$'+n;

        li.appendChild(a);
        KeymanWeb_KbdList.appendChild(li);
    }
    kmw_kbdon.getElem().appendChild(KeymanWeb_KbdList);
};

/* Load stored settings for KeymanWeb for the current user/domain */
function kmw_loadcookie()
{
    // cookie string: kmw_defaults=keyboardname,keyboardindex,osk_visible:true|false
    
    var nameEQ = "kmw_defaults=";
	var ca = document.cookie.split(';')
	var val = null;
	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)
		{
		    val = c.substring(nameEQ.length,c.length);
		    break;
		}
	}
	
	if(val == null) return; // no cookie set
	
	ca = val.split(',');
	if(ca.length < 3) return;
	if(KeymanWeb.GetKeyboards().length > 1)
	{
	  for(var i = 0; i < kmw_keyboards.length; i++)
	    if(kmw_keyboards[i].InternalName == ca[0] && kmw_keyboards[i].Index == ca[1])
	    {
	      kmw_switchkbd(i, false);
	      break;
	    }
	}
	else if(ca[0] != '' && !kmw_activebydefault) kmw_switchkbd_single();
	
	if(kmw_showosk.toString() != ca[2]) kmw_switchosk();
}

/* Save settings for KeymanWeb for the current user/domain */
function kmw_updatecookie()
{
  var name = KeymanWeb.GetActiveKeyboard();
  if(name == '' || kmw_lastactivekeyboard < 0) var value = ',0,'+kmw_showosk;
  else var value = name+','+kmw_keyboards[kmw_lastactivekeyboard].Index+','+kmw_showosk;
    
	var date = new Date();
	date.setTime(date.getTime()+(180*24*60*60*1000));
	var expires = "expires="+date.toGMTString();

	document.cookie = "kmw_defaults="+value+"; "+expires+"; path=/";    
}

/* Watch for Ctrl+/ and Ctrl+Shift+/ keyboard switch hotkeys */
kmw_addevent(document, 'keyup', 
  function(e)
  { 
    if(!e) e = window.event;
    if (e.keyCode) var Lcode = e.keyCode;
    else if (e.which) var Lcode = e.which;
    else return 0;
    
    if(e.shiftKey != null)
      var Lmodifiers = 
        (e.shiftKey ? 0x10 : 0) |
        (e.ctrlKey ? (e.ctrlLeft ? 0x20 : 0x20) : 0) | 
        (e.altKey ? (e.altLeft ? 0x40 : 0x40) : 0);
    else
      var Lmodifiers = 
        ((e.modifiers & 1) == 1 ? 0x40 : 0) |
        ((e.modifiers & 2) == 2 ? 0x20 : 0) |
        ((e.modifiers & 4) == 4 ? 0x10 : 0);

    if(Lcode == 191)
    { 
      if(Lmodifiers == 0x20) { kmw_switchkbd_single(); e.returnValue = 0; if(e && e.preventDefault) e.preventDefault(); e.cancelBubble = true; return false; }
      if(Lmodifiers == 0x30) { kmw_switchkbd_next(); e.returnValue = 0; if(e && e.preventDefault) e.preventDefault(); e.cancelBubble = true; return false; }
    }
    return true;
  }
);
