ajax! Enterでフォーカス移動

日本では昔から需要のあるフォーカスのEnterキー移動。
欲しくなったので実装してみました。すんません、ajaxでもなんでもないです・・・

prototype.jsを使ってクロススクリプティングになっています。
IEFirefoxOperaで動作確認してあります。
どなたか偉い人、まずい部分を指摘、もしくはリファクタリングよろしくお願いします〜。

var TabEmurator = Class.create()
TabEmurator.prototype = {
  initialize: function(hook_event_key, options) {
    this.event_key = hook_event_key || Event.KEY_RETURN;
    this.options = {
      tags: ['input', 'select'],	//エミュレート対象とするタグ
      auto_numbring: true,		//タブインデックスの自動設定の有無
    };
    Object.extend(this.options, options || {});
    
    this.setup();
  },
  setup: function() {
    var all_tags = document.getElementsByTagName('*') || document.all;		//Get AllTag
    var elements = new Array();

    if (this.options.auto_numbring) {
      //エミュレート対象タグの取得
      elements = $A(all_tags).select*1;
      }).bind(this));
      //オートナンバリング
      elements.each(function(element, index) {
        element.tabIndex = index+1;		//1がスタート
      });
    } else {
      //エミュレート対象タグの取得、タブインデックスの昇順でソート
      elements = $A(all_tags).select 0 &&
               this.options.tags.include(child_tag.tagName.toLowerCase(">*2;
      }).bind(this)).sortBy(function(element) {
        return element.tabIndex;
      });
    }
    this.elements = elements;
  },
  move: function(event) {
    if(event.keyCode != this.event_key) return;
    var base_element = Event.element(event);
    
    if (base_element.type != 'button') {
      Event.stop(event);
      var next = event.shiftKey ? this._prev(base_element) : this._next(base_element);
      try{ Field.activate(next); /* focus+select */}
      catch(e) { return; }
    }
  },
  _prev: function(base_element) {
    var min_tabIndex = this.elements[0].tabIndex;

    //タブ値がMAXの場合、次のフォーカスタグは最小タブ値とする。
    if (base_element.tabIndex == min_tabIndex) {
      return this.elements[this.elements.length-1];
    } else {
      for(var i=this.elements.length-1; i>=0; i--) {
        var next = this.elements[i];
        //フォーカス移動
        if (next.tabIndex < base_element.tabIndex ) {
          return next;
        }
      }
    }
    return;
  },
  _next: function(base_element) {
    var max_tabIndex = this.elements[this.elements.length-1].tabIndex;

    //タブ値がMAXの場合、次のフォーカスタグは最小タブ値とする。
    if (base_element.tabIndex == max_tabIndex) {
      return this.elements[0];
    } else {
      for(var i=0, len=this.elements.length; i base_element.tabIndex ) {
          return next;
        }
      }
    }
    return;
  }
}

コードの説明をすると、
オプションの tags: でタブ移動をエミュレートしたい対象のタグを指定して、
auto_numbring: で、タブインデックスの番号付けを自動か手動かを指定できます。
後は、こんな感じにloadイベントで呼び出してください。
*やっぱり、keydownイベントの登録処理は内部に持たせてたほうがいいかな。

  var tab_emu = null;
  window.onload = function() {
    tab_emu = new TabEmurator(13, {tags:['input']});
    $A(tab_emu.elements).each(function(element) {
      Event.observe(element, 'keydown', tab_emu.move.bind(tabemu), false);
    });


Tags: , ,

*1:function(child_tag) { return !child_tag.disabled && child_tag.type != "hidden" && this.options.tags.include(child_tag.tagName.toLowerCase(

*2:function(child_tag) { return !child_tag.disabled && child_tag.type != "hidden" && child_tag.tabIndex > 0 && this.options.tags.include(child_tag.tagName.toLowerCase(