Subversion Repositories wimsdev

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.    DynAPI Distribution
  3.    Key Event Extensions by Henrik Våglin (hvaglin@yahoo.com)
  4.  
  5.    The DynAPI Distribution is distributed under the terms of the GNU LGPL license.
  6.  
  7.    Requirements:
  8.         dynapi.api
  9. */
  10. function DynKeyEvent(type,src) {
  11.         this.DynEvent = DynEvent;
  12.         this.DynEvent(type,src);
  13.         this.charKey=null;
  14. };
  15. var p=dynapi.setPrototype('DynKeyEvent','DynEvent');
  16. p.getKey=function() {
  17.         return this.charKey;
  18. };
  19. DynKeyEvent._keyEventListener=function(e) {
  20.         var dynobj=this._dynobj;
  21.         if(!dynobj) return true;
  22.         var dyndoc=dynobj.doc._dynobj;
  23.         if(!dyndoc) return true;
  24.         if(!e) var e=dyndoc.frame.event;
  25.  
  26.         var evt=new DynKeyEvent(e.type,dynobj);
  27.         evt.which=(e.keyCode)?e.keyCode:e.which;
  28.         var key=String.fromCharCode(evt.which).toLowerCase();
  29.         if((key>='a'&&key<='z')||(key>='0'&&key<='9')) evt.charKey=key;
  30.         evt.spaceKey=(evt.which==32);
  31.         evt.enterKey=(evt.which==13);
  32.         evt.tabKey=(evt.which==9||evt.which==65289);
  33.         evt.leftKey=(evt.which==37||evt.which==52||evt.which==100||evt.which==65460);
  34.         evt.rightKey=(evt.which==39||evt.which==54||evt.which==102||evt.which==65462);
  35.         evt.upKey=(evt.which==38||evt.which==56||evt.which==104||evt.which==65464);
  36.         evt.downKey=(evt.which==40||evt.which==50||evt.which==98||evt.which==65458);
  37.         evt.altKey=(e.modifiers)?false:(e.altKey||e.altLeft||evt.which==18||evt.which==57388);
  38.         evt.ctrlKey=(e.modifiers)?(e.modifiers&Event.CONTROL_MASK):(e.ctrlKey||e.ctrlLeft||evt.which==17||evt.which==57391);
  39.         evt.shiftKey=(e.modifiers)?(e.modifiers&Event.SHIFT_MASK):(e.shiftKey||e.shiftLeft||evt.which==16||evt.which==57390);
  40.  
  41.         dynobj.invokeEvent(evt.type,evt);
  42.         if(evt.defaultValue==false) {
  43.                 if(e.cancelBubble) e.cancelBubble=true;
  44.                 if(e.stopPropagation) e.stopPropagation();
  45.         }
  46.         return evt.defaultValue;
  47. };
  48.  
  49. TabManager={};
  50. TabManager._c=0; // Current tab manager index.
  51. TabManager._all=[];
  52. TabManager._active=false;
  53. TabManager._activeTimeout=function() { // Prevent duplcate keydown events in NS4.
  54.         TabManager._active=true;
  55.         setTimeout('TabManager._active=false;',25);
  56. };
  57. TabManager._getForm=null;
  58. TabManager.getForm=function(p) { // Prevent default tab focus in Mozilla.
  59.         if(TabManager._getForm) return;
  60.         TabManager._getForm=p;
  61.         var html='<form name="__frm" onsubmit="return false;"><input name="__tab" size=1></form>';
  62.         return p.addChild(new DynLayer(html),'__lyr');
  63. };
  64. TabManager._grabFocus=function() {
  65.         var form=TabManager._getForm.__lyr;
  66.         setTimeout(form+'.doc.forms.__frm.__tab.focus();',0);
  67. };
  68. TabManager._el={};
  69. TabManager._el.onkeydown=function(e) {
  70.         if(TabManager._getForm) { // User must have inserted TabManager form.
  71.                 if(TabManager._active) return;
  72.                 TabManager._activeTimeout();
  73.         }
  74.         var i1,o1,l1,i2,o2,l2;
  75.         var nextKey=(e.tabKey||e.rightKey);
  76.         var prevKey=((e.shiftKey&&e.tabKey)||e.leftKey);
  77.         var submitKey=(e.enterKey||e.spaceKey);
  78.         i1=TabManager._c; o1=TabManager._all[i1]; l1=TabManager._all.length;
  79.         i2=o1._tabGroup._c; o2=o1._tabGroup._all[i2]; l2=o1._tabGroup._all.length;
  80.         if(nextKey||prevKey) { // Cycle group.
  81.                 if(o2._hasFocusEvents) o2.setFocus(false,o2._focusBubble);
  82.                 else o2.invokeEvent('blur');
  83.                 if(prevKey) i2=(i2==0)?l2-1:i2-1;
  84.                 else i2=(i2==l2-1)?0:i2+1;
  85.                 o2=o1._tabGroup._all[i2]; o1._tabGroup._c=i2;
  86.                 if(o2._hasFocusEvents) o2.setFocus(true,o2._focusBubble);
  87.                 else o2.invokeEvent('focus');
  88.         }              
  89.         else if(e.upKey||e.downKey) { // Cycle manager.
  90.                 if(o2._hasFocusEvents) o2.setFocus(false,o2._focusBubble);
  91.                 else o2.invokeEvent('blur');
  92.                 if(e.upKey) i1=(i1==0)?l1-1:i1-1;
  93.                 else i1=(i1==l1-1)?0:i1+1;
  94.                 o1=TabManager._all[i1]; TabManager._c=i1;
  95.                 i2=o1._tabGroup._c;
  96.                 o2=o1._tabGroup._all[i2];
  97.                 if(o2._hasFocusEvents) o2.setFocus(true,o2._focusBubble);
  98.                 else o2.invokeEvent('focus');
  99.         } else if(submitKey) {
  100.                 o2.invokeEvent('submit');
  101.         }
  102.         e.preventDefault();
  103.         if(TabManager._getForm) TabManager._grabFocus();
  104. };
  105. DynElement.prototype.createTabManager=function() {
  106.         var p=this, c=p.children; if(!c) return;
  107.         var args=(arguments.length)?arguments:c;
  108.         var l=args.length, s; if(!l) return;
  109.         if(p._tabGroup) delete p._tabGroup;
  110.         p._tabGroup={ _c:0, _all:[] };
  111.         for(var i=0;i<l;i++) {
  112.                 c=args[i];
  113.                 p._tabGroup._all[i]=c;
  114.                 c._hasTabManager=true;
  115.                 if(!c._submitFn) {
  116.                         s=c.id.replace(/-/g,'.')+'()'; // Element id callback.
  117.                         c._submitFn=s;
  118.                 }
  119.         }
  120.         l=TabManager._all.length; TabManager._all[l]=p;
  121.         if(l==0) dynapi.onLoad(function() {
  122.                         dynapi.document.addEventListener(TabManager._el);
  123.                 });
  124. };
  125. DynElement.prototype.updateTabManager=function() {
  126.         var tm=TabManager, all=tm._all[TabManager._c]; if(!all) return;
  127.         var old=all._tabGroup; if(!old||old._all[old._c]==this) return;
  128.         var p=this.parent, l;
  129.         var tg=(p&&p._tabGroup)?p._tabGroup:null; if(!tg) return;
  130.         l=tg._all.length;
  131.         for(var i=0;i<l;i++) if(tg._all[i]==this) { tg._c=i; break; }
  132.         l=tm._all.length;
  133.         for(var i=0;i<l;i++) if(tm._all[i]==p) { tm._c=i; break; }
  134. };
  135. DynElement.prototype.addTabListeners=function(el) {
  136.         if(el&&this._tabGroup) {
  137.                 var a=this._tabGroup._all;
  138.                 for(var i in a) a[i].addEventListener(el);
  139.         }
  140. };
  141. DynElement.prototype.addSubmitFn=function(fn) {
  142.         if(fn) this._submitFn=fn;
  143. };
  144. DynElement.prototype.callSubmitFn=function() {
  145.         var f=this._submitFn;
  146.         if(typeof(f)=='function') f();
  147.         else if(typeof(f)=='string') eval(f);
  148. };
  149.  
  150. DynElement.prototype.captureKeyEvents=function() {
  151.         var elm=(this.getClassName()=='DynLayer')?this.elm:this.doc;
  152.         if(!elm||this._hasKeyEvents) return true;
  153.         if(elm.addEventListener) {
  154.                 elm.addEventListener("keydown",DynKeyEvent._keyEventListener,false);
  155.                 elm.addEventListener("keypress",DynKeyEvent._keyEventListener,false);
  156.                 elm.addEventListener("keyup",DynKeyEvent._keyEventListener,false);
  157.         }
  158.         else {
  159.                 if(elm.captureEvents)
  160.                         elm.captureEvents(Event.KEYPRESS|Event.KEYDOWN|Event.KEYUP);
  161.                 elm.onkeydown=elm.onkeypress=elm.onkeyup=DynKeyEvent._keyEventListener;
  162.         }
  163.         this._hasKeyEvents=true;
  164.         return false;
  165. };
  166. DynElement.prototype.releaseKeyEvents=function() {
  167.         var elm=(this.getClassName()=='DynLayer')?this.elm:this.doc;
  168.         if(!elm||!this._hasKeyEvents) return true;
  169.         if(elm.removeEventListener) {
  170.                 elm.removeEventListener("keydown",DynKeyEvent._keyEventListener,false);
  171.                 elm.removeEventListener("keypress",DynKeyEvent._keyEventListener,false);
  172.                 elm.removeEventListener("keyup",DynKeyEvent._keyEventListener,false);
  173.         }
  174.         else {
  175.                 if(elm.releaseEvents)
  176.                         elm.releaseEvents(Event.KEYPRESS|Event.KEYDOWN|Event.KEYUP);
  177.                 elm.onkeydown=elm.onkeypress=elm.onkeyup=null;
  178.         }
  179.         this._hasKeyEvents=false;
  180.         return false;
  181. };
  182.  
  183. DynDocument.prototype.captureHotKey = function(key,fn){
  184.         var klst=((key+'').toLowerCase()).split('+');
  185.         klst.sort();
  186.         key=klst.join('+');
  187.         if(!this._hotKeys){
  188.                 this._hotKeys={};
  189.                 this._keyDn={};
  190.                 this._keyLst='';
  191.                 this.captureKeyEvents();
  192.                 this.addEventListener({
  193.                         onkeydown:function(e){
  194.                                 var k = e.which;
  195.                                 var o = e.getSource(); 
  196.                                 // to-do: add opera v7 key code (57xxx), e.g 57388
  197.                                 if (k==13) k="enter";
  198.                                 else if(k==27) k="esc";
  199.                                 else if(k==45) k="insert";
  200.                                 else if(k==46) k="delete";
  201.                                 else if(k==36) k="home";
  202.                                 else if(k==35) k="end";
  203.                                 else if(k==33) k="pgup";
  204.                                 else if(k==34) k="pgdn";
  205.                                 else if(k==38) k="up";
  206.                                 else if(k==40) k="down";
  207.                                 else if(k==37) k="left";
  208.                                 else if(k==39) k="right";                              
  209.                                 else if(e.altKey && !o._keyDn['alt']) k="alt";
  210.                                 else if(e.ctrlKey && !o._keyDn['ctrl']) k="ctrl";
  211.                                 else if(e.shiftKey && !o._keyDn['shift']) k="shift";
  212.                                 else k=(String.fromCharCode(k)).toLowerCase();
  213.                                 if(!o._keyDn[k]) {
  214.                                         // store new key in keyDn array
  215.                                         o._keyLst+=(((o._keyLst)? '+':'')+k); // build key list
  216.                                         var ar=o._keyLst.split('+');
  217.                                         ar.sort();
  218.                                         o._keyLst=ar.join('+');
  219.                                         o._keyDn[k]=true;
  220.                                 }
  221.                                 k=o._hotKeys[o._keyLst];
  222.                                 if(k){
  223.                                         o._keyLst='';o._keyDn={};
  224.                                         if(typeof(k)=='string') return eval(k); else return k();
  225.                                 }
  226.                         },
  227.                         onkeyup:function(e){
  228.                                 var o=e.getSource();   
  229.                                 o._keyLst='';o._keyDn={};
  230.                         }
  231.                 });
  232.         }
  233.         this._hotKeys[key]=fn;
  234. };
  235. DynDocument.prototype.releaseHotKey = function(key){
  236.         if(this._hotKeys) delete this._hotKeys[key];
  237. };
  238.  
  239.