//--------------------------------------------------------------------------------
//
// FormFocusManager.js
//   ver. 0.1.0 at 2007-09-08
//
// required:
//   prototype.js
//
//--------------------------------------------------------------------------------
var FormFocusManager = Class.create();
FormFocusManager.prototype = {
  initialize: function( form, flg_notFocus ) {
    if( ! form ) { return false; }

    this.body     = $( form ); // フォーム本体
    this.elements = [];        // 監視対象フォーム要素の集合
    this.position = 0;         // 監視中フォームの位置

    this.apply();
    this.startManage();

    this.body.onsubmit = function() { return false; } // フォームの Enter 押下による submit 動作を無効にする
    if( ! flg_notFocus ) { this.elements[ this.position ].focus(); }
    return;
  },

  /**
   * 監視対象となるフォーム要素をオブジェクトに割り付ける
   * ffm-ignore なクラスの要素は対象としない
   */
  apply: function() {
    var elements = this.body.elements;
    for( var i = 0; i < elements.length; i++ ) {
      var element = elements[i];
      if( element.className.match( 'ffm-ignore' ) ) { continue; }
      if( element.type.match( /^(hidden)$/ ) ) { continue; }
      //if( element.type == 'submit' ) { Event.observe( element, 'click', this.executeFunction.bindAsEventListener( this ), false ); }
        
      this.elements.push( elements[i] );
    }
  },

  /**
   * 監視対象のフォーム要素にイベントリスナーをセットする
   */
  startManage: function() {
    for( var i = 0; i < this.elements.length; i++ ) {
      var element = this.elements[i];
      Event.observe( element, 'keypress', this.transitFocus.bindAsEventListener( this ), false );
      Event.observe( element, 'focus',    this.adjustPosition.bindAsEventListener( this ), false );
    }
    return;
  },

  /*
   * keypressイベント
   *  Enter押下時にフォーカスを遷移する
   */
  transitFocus: function( e ) {
    if( e.keyCode != 13 ) { return; }
    // textareaでは，ctrl + Enter で次の，ctrl + shift + Enter 前の要素へそれぞれフォーカス遷移する
    if( this.elements[ this.position ].nodeName.match( /textarea/i ) ) {
      if( e.ctrlKey ) { e.shiftKey ? this.position-- : this.position++; }
    }
    // その他の要素では，Enter で次の，shift + Enter で前の要素へそれぞれフォーカス遷移する
    else {
      if( e.ctrlKey ) { this.executeFunction(); }
      e.shiftKey ? this.position-- : this.position++;
    }

    // 最初の要素の位置より手前になった場合，最後の要素の位置をセット
    // 最後の要素の位置を超えた場合，関数を実行し，最初の要素の位置をセット
    var l = this.elements.length;
    if( this.position < 0 )  { this.position += l; }
    if( this.position >= l ) { this.executeFunction(); this.position -= l; }

    this.elements[ this.position ].focus();
    return;
  },

  /*
   * focusイベント
   *   this.position をフォーカスされた要素の位置にセットする
   */
  adjustPosition: function( e ) {
    var element = Event.element( e );
    for( var i = 0; i < this.elements.length; i++ ) {
      if( element == this.elements[ i ] ) {
        this.position = i;
        break;
      }
    }
    return;
  },

  /*
   * 
   */
  setFunction: function( func ) {
    this.func = func;
    return;
  },
  
  /*
   * 指定された関数を実行する．デフォルトでは submit 処理を行う
   */
  executeFunction: function() {
    this.func ? this.func.call() : this.body.submit();
    return;
  }

};
