Enter/Tabでフォーカス移動とFunctionKey制御 jqKeyプラグイン更新

jqKey.js書き直し

ネタがないので、微妙に人気のjqKey.jsを大幅に機能強化しました

Enter/Tab項目移動とFunctionKey制御をplugin化 - せかにゃ~

主な機能
  • Enter/Tabでフォームのフォーカスを移動*1
  • ファンクションキーイベントトラップ
  • Document内に複数のFormがあっても利用可(new)
  • [Ctrl]+[Enter]押下時に入力項目のJump機能追加(※TEXT、TEXTAREAのみ)(new)
  • 明細テーブル等で、フォームオブジェクト名が同じ場合に限り上下キーで移動可 (new)
  • オプションパラメータを変更可(new)
その他
  • jQuery Ver1.8以上(たぶん1.4でも動く)
  • Browser IE9/11,Firefox33,Chrome38にてテスト

MacAndroidは、未検証

  • IE8以下のサポート廃止
  • Aタグ等・フォームオブジェクトでない場合は、フォーカス移動は仕様上できません
  • EnterでフォームのSubmitは、仕様上できません*2

Demo

API

Methods

disable

Returns:jQuery

  • jqKeyを無効にします

Code examples:

$(".selector").jqKey("disable");

enable

Returns:jQuery

  • jqKeyを有効にします

Code examples:

$(".selector").jqKey("enable");

destroy

Returns:jQuery

  • 完全にjqKeyの機能を削除します

Code examples:

$(".selector").jqKey("destroy");

dom

Returns:jQuery

  • jqKeyのフォームオブジェクトキャッシュを更新します

Code examples:

$(".selector").jqKey("dom");

Options

Enter

Type :boolean
Default:true

  • Enterで次フォームオブジェクトに移動します

Code examples:

$(".selector").jqKey({Enter:true});

Tab

Type :boolean
Default:true

  • Tabで次フォームオブジェクトに移動します

Code examples:

$(".selector").jqKey({Tab:true});

LeftRight

Type :boolean
Default:false

  • 左右キーで次フォームオブジェクトに移動します

Code examples:

$(".selector").jqKey({LeftRight:true});

UpDown

Type :boolean
Default:false

  • 上下キーで同一フォームオブジェクト名を移動します

Code examples:

$(".selector").jqKey({UpDown:true});

CtrlEnter

Type :{Name:[string array],bgColor:"color name"}
Default:{Name:[],bgColor:'lightblue'}

  • Ctrl+Enter押下で、指定テキストオブジェクト名に順番にジャンプします
  • ジャンプ先テキストオブジェクトの背景色を設定します
  • テキストオブジェクトとテキストエリアのみ設定可能です
  • 後からの追加オプションとしての設定はできません
  • 存在しないオブジェクト名を設定すると、暴走します

Code examples:

$(".selector").jqKey({CtrlEnter:{
          Name:['TextObjectName1','TextObjectName2']
         ,bgColor:'yellow'
});

F1~12

Type :function(object,{shift:boolean,ctrl:boolean,alt:boolean,fKey:fKeyName});
Default:null

  • フォーカスのフォームオブジェクトで、ファンクションキーを押下した時に設定した関数を実行

Code examples:

$(".selector").jqKey({
  F1:function(object,option){
    var w = "PUSH Name:"+object.name+":id:"+object.id;
        w += "\nShift:"+option.shift;
        w += "\nCtrl :"+option.ctrl;
        w += "\nAlt  :"+option.alt;
        w += "\nFKey :"+option.fKey;
    alert(w);
  }
});

ESC

Type :function();
Default:null

  • フォーカスのフォームオブジェクトで、ファンクションキーを押下した時に設定した関数を実行
  • ESCキー2回押時のフォームリセットが無効化されます

Code examples:

$(".selector").jqKey({
  ESC:function(){
    alert("PUSH ESCキー");
  }
});
jqKey.js SourceCode
//=============================================================================
// jqKey
// Ver 0.2  ↑↓移動対応     2013.07.26
// Ver 0.3  OnOff対応     2013.11.29
// Ver 0.4  forms[0]依存解消・IE8以下サポート外  2014.11.09
//  MIT Licence  (自由に使ってください)
//  programed by Hidepyon
//  URL          http://hidepyon.hateblo.jp/entry/2014/11/09/232716
//=============================================================================
(function($){
 var setting = [];
 var d = document;
 var RangeId;
 var $df;
 //==============================
 // window help
 //==============================
 window.onhelp = function(){
  if(window.event) window.event.returnValue = false;
  return false;
 };
 
 $.fn.jqKey = function(options){
  var method = function(e){
   if(!setting.Active) return true;

   this.getCursorPosition = function(srcObj){
    var type = srcObj.type;
    var ln=0;//カーソル位置
    var w;//ワード
    var wln=0;//ワード長
    w = srcObj.value;
    wln = w.length;
    var s;
    switch(type){
     case "text":
     if(srcObj.selectionStart!=undefined){
      //IE 9 upper
      ln = srcObj.selectionStart;
     }
//IE8以下非対応のため(動作不良)================================================
//     else{
//      var sobj = (document.selection?document.selection:window.getSelection());
//      if(sobj.createRange){
//       s =sobj.createRange();
//      }
//      s.moveStart("character", - wln);
//      ln = s.text.length;
//     }
//=============================================================================
     break;
     case "textarea":
     if(srcObj.selectionStart!=undefined){
      //IE 9 upper
      ln = srcObj.selectionStart;
     }
//IE8以下非対応のため(動作不良)================================================
//     else{
//      var sobj = (document.selection?document.selection:window.getSelection());
//      if(sobj.createRange){
//       s =sobj.createRange();
//      }
//      var p = s.parentElement();
//      if(p==null||p.type!="textarea"){
//       ln=0;
//       wln=0;
//      }else{
//       var bm = s.getBookmark();
//       var contentsOrg = srcObj.value;
//       var marker = "###"+Math.floor(Math.random()*10000);
//       s.text = marker+s.text+marker;
//       var contents = srcObj.value;
//       
//       var start = contents.indexOf(marker);
//       contents = contents.replace(marker,"");
//       var end = contents.indexOf(marker);
//       
//       srcObj.value = contentsOrg;
//       s.moveToBookmark(bm);
//       s.select();
//       ln = end;
//       wln = contentsOrg.length;
//      }
//     }
//=============================================================================
     break;
     default:// "checkbox","button","radio","select-one","select-multiple"
     ln=0;wln=0;
     break;
    }

    return {First:(ln==0),Last:(ln==wln)};

   }

   var Focus_Move = function($frmObjs,shift){
    var Focus_Check = function(o){
     try{
      o.focus();
      if(o.select&&o.type!="button") o.select();
      return true;
     }catch(e){return false;}
    };
    var isVisible = function(o,n){
     if(n==undefined)n=10;
     while(--n>0){
      if(o.tagName=="BODY") return true;
      var os = o.style;
      if(os.display=="none"||os.visibility=="hidden") return false;
      o=o.parentElement;
     }
     return true;
    };

    //フォームオブジェクトが何番目か探す
    var ln = $frmObjs.length;
    if(ln<=0) return true;
    var i;
    for (i=0;i<ln;i++){
     if ($frmObjs[i]==obj) break;
    }
    //フォーカスを取得できないものは飛ばします
    var mv = (shift?-1:1);
    var j = (ln+i+mv) % ln;
    var Fo,Fs;
    var num = 0;
    while(true){

     Fo = $frmObjs[j];
     Fs = Fo.style;
     if (Fo.type!="hidden" &&
      !Fo.disabled &&
      Fo.tabIndex!=-1 &&
      isVisible(Fo)){

      //対象のオブジェクトを戻す
      if(Focus_Check(Fo)){
       break;//Focus成功
      }else{
       //Hitしない場合
       if(++num>50)break;
      }
     }
     j=(j+mv+ln) % ln;
    }
    return false;
   };

   var k = e.keyCode;
   var s = e.shiftKey;
   var c = e.ctrlKey;
   var a = e.altKey;
   var obj = e.target;
   
   var blKey = true;
   if (!setting.Enter&&k==13) return true;
   if (!setting.Tab&&k==9) return true;
   switch(k){
    case 32: //Space
     switch(obj.type){
     case"radio":case"checkbox": //Spaceで選択
      setTimeout(function(){$(obj).trigger("click");},0);
      blKey = false; //移動しない
      break;
                        default:
     }
    case 13: //Enter
     switch(obj.type){
     case"button":
     case"file":
      blKey = true;
      break;
     case"text":case"select-one":case"select-multiple":case"textarea":
      var CEln = setting.CtrlEnter.Names.length;
      if(c && CEln>0){
       var dfln = $df.length;
       while(dfln-->0){
        blKey = Focus_Move($df,false);
        obj = d.activeElement;
        for(var i=0;i<CEln;i++){
         if(obj.name==setting.CtrlEnter.Names[i]){
          return false;
         }
        }
       }
       blKey = true;
      }else{
       if (obj.type!="text-area"){
        blKey = false;
       }else{
        blKey = true;
       }
      }
      break;
     default:
      blKey = false;
      break;
     }
     //keyイベントを処理するもののみ抽出
     if (!blKey){
      //次のフォームオブジェクト探す
      blKey = Focus_Move($df,s);
     }
    break;
    case 9:  //tab
     switch(obj.type){
     case"file":
      blKey = true;
      break;
     default:
      //次のフォームオブジェクト探す
      blKey = Focus_Move($df,s);
      break;
     }

    break;
    case 8:  //backspace
     switch(obj.type){
     case"text":case"textarea":
      blKey = true;
      break;
     default:
      blKey = confirm("backspaceが押されました。\n前ページへ移動しますか?");
      break;
     }

    break;
    case 27://ESC
     if(setting.ESC){
      setting.ESC();
      blKey = false;
     }
    break;
    case 38://Up
     if(setting.UpDown && obj.name!=""){
      blKey = Focus_Move(d.getElementsByName(obj.name),true);
     }
     break;
    case 40://Down
     if(setting.UpDown && obj.name!=""){
      blKey = Focus_Move(d.getElementsByName(obj.name),false);
     }
     break;
    case 37://Left
     if(setting.LeftRight){
      if(getCursorPosition(obj).First){
       blKey = Focus_Move($df,true);
      }
     }
     break;
    case 39://Right
     if(setting.LeftRight){
      if(getCursorPosition(obj).Last){
       blKey = Focus_Move($df,false);
      }
     }
     break;
    default:
     if(k>=112&&k<=123){
      var fKeyNm = "F"+(k-111);
      var F = setting["F"+(k-111)];
      if(F){
       if(window.event)window.event.keyCode = 0;
       e.keyCode = 0;
       blKey = false;
       F(obj,{shift:s,ctrl:c,alt:a,fKey:fKeyNm});
      }
     }
    break;
   }
   return blKey;
  };
  var bind = function(){
   var $o = $(":input[type!=hidden]",RangeId);
   $df = $o.keydown(function(e){
    return method(e);
   });
  };
  var unbind = function(){
   $df.unbind("keydown");
  };

  var DOM_init = function(id){
   if(RangeId==undefined){
    if(setting.CtrlEnter.Names.length>0){
     //CtrlEnterオプションあれば、背景色設定
     $("<style type='text/css'>.jqKeyCtrlEnter{background-color:"+setting.CtrlEnter.bgColor+"}</style>").appendTo("head");
     $.each(setting.CtrlEnter.Names,function(idx,vl){
      $("[name='"+vl+"']").addClass("jqKeyCtrlEnter");
     });
    }
   }else{
    unbind();
   }
   RangeId =id;
   bind();
  };
  var defaults = {
   "Enter":false,
   "Tab":false,
   "F1":null,"F2":null,"F3":null,"F4":null,"F5":null,"F6":null,
   "F7":null,"F8":null,"F9":null,"F10":null,"F11":null,"F12":null,
   "ESC":null,
   "UpDown":false,
   "LeftRight":false,
   "CtrlEnter":{Names:[],bgColor:"lightblue"},
   "Active":true
  };
  if(typeof(options)=="string"){
   if(setting.length!=0){
    if(options=="disable"){
     setting.Active = false;
    }else if(options=="enable"){
     setting.Active = true;
    }else if(options=="dom"){
     DOM_init(this);
    }else if(options=="dispose"){
     setting = new Array();
     unbind();
    }

   }
   return;
  }else{
   setting = $.extend(true,{},(setting.length!=0)?setting:defaults,options);
  }

  DOM_init(this);
  return (this);//メソッドチェーン
 };
})(jQuery);

まだテスト不足です
ご自由に改造して使ってください
不具合ありましたら、修正箇所をこっそり教えていただけるとたすかります

*1:ホストコンピュータの仕様を再現!

*2:EnterでSubmit防止?

住所から郵便番号変換のAutoComplete対応版

住所から郵便番号変換のメモ - Hidepyonのブログ
jquery UI AutoComplete対応してみました。

前回同様「ricollab 郵便番号検索」を利用

郵便番号 または 住所 → 郵便番号 と 住所 を出力します。

住所項目に適当な 郵便番号または住所を入力してみてください。

Demo

郵便番号問合せ
住所    
郵便番号
住所








ソース

<!-- スタイルシート設定 -->
<!-- jquery UI スタイルシート -->
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.11.2/themes/black-tie/jquery-ui.css"/>
<!-- autocomplete スクロール表示 -->
<style type="text/css">
.ui-autocomplete {
  max-height: 250px;overflow-y: auto;overflow-x: hidden;padding-right: 20px;
}
* html .ui-autocomplete {
  width: 400px;height: 250px;
}
</style>

    <!-- Jquery -->
    <script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
    <!-- Jquery UI -->
    <script language="javascript" type="text/javascript" charset="utf-8" src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
    <script language="javascript" type="text/javascript">
$(function () {
  var txt_AddressToZip = document.getElementById('txt_AddressToZip');
  //==============================
  // AutoCompleteセット
  //==============================
  var AutoComp_On = function () {
    AutoComp_Off();
    var $lbl_Msg = $("#lbl_Msg");

$(txt_AddressToZip).autocomplete({
   source: function (request, response) {
     $.ajax({
       url: "http://zip.ricollab.jp/search"
       , data: { q: request.term, type: "json", count: 50 }
       , dataType: "jsonp"
     }).done(function (data) {
       var result = $.map(data.result, function (item) {
         var zip = item.zipcode.substring(0, 3) + "-" + item.zipcode.substring(3);
         return { label: zip+" "+item.address , value: {"adr":item.address,"zip":zip} }
       });
       var msg = data.totalResults.toString() + "件";
       $lbl_Msg.text((data.totalResults > 50) ? msg + "中50件表示" : msg)
       response(result);
     }).fail(function (jqXHR, textStatus, errorThrown) {
       alert(textStatus);
     });
  }
  , delay: 50
  , minLength: 3
  , select: function (event, ui) {
     if (ui.item) {
       this.value = ui.item.value.adr;
       $('#txt_Address').val(ui.item.value.adr.replace("−", "-"));
       $('#txt_Zipcode').val(ui.item.value.zip);
       return false;
     }
  }
  , search: function (event, ui) {
    if (event.keyCode == 229) return false;
    if (/^\d{3}\-\d{1,4}$/.test(txt_AddressToZip.value)) {
      txt_AddressToZip.value = txt_AddressToZip.value.replace("-", "");
    }
    return true;
  }
  , focus: function (event, ui) {
    $(this).val(ui.item.value.adr);
    return false;
  }
     //,open: function(event, ui){}
     //,close: function(event, ui){}
  }).keyup(function (event) {
    if (event.keyCode == 13 || event.keyCode == 8) {
      $(this).autocomplete("search");
    }
  }).data("autocomplete")._renderItem = function (ul, item) {
    var wk = "<a><table style='font-size:9pt;'><tbody><tr>";
    wk += "<td style='width:090px'>〒" + item.value.zip + "</td>";
    wk += "<td style='width:300px'>" + item.value.adr + "</td>";
    wk += "</tr></tbody></table></a>";
    return $("<li></li>").data("item.autocomplete", item).append(wk).appendTo(ul);
  };
}
  var AutoComp_Off = function (p) {
    $('#txt_AddrToZip').autocomplete("destroy");
  }
  //==============================
  // リセット
  //==============================
  var fn_RST = function () {
    $('#txt_AddressToZip').val("");
    $('#txt_Zipcode').val("");
    $('#txt_Address').val("");
  }
  //==============================
  // 終了
  //==============================
  var fn_END = function () {
//  AutoComp_Off();
    var ans = "";
    var address = $('#txt_Address').val();
    var zipcode = $('#txt_Zipcode').val();
    alert("Answer:address:"+address+":zipcode:"+zipcode);
  }

  $("#cmdEND").click(function () {
    fn_END();
  });
  $("#cmdRST").click(function () {
    fn_RST();
  });
  //====================================================
  //初期値設定
  //====================================================
  txt_AddressToZip.focus();
  AutoComp_On();
  setTimeout(function(){$('#txt_AddressToZip').autocomplete("search");},2000);
});
</script>

RSS をだらだら表示してみる

RSSを自動で定期的に取得し、画面に表示します。

ソース

<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
//Google AJAX Feed API 利用してRSSを変換
google.load("feeds", "1");
//取得先RSSリンク一覧
function initialize() {
	var feedurl = [
	"http://www3.nhk.or.jp/rss/news/cat1.xml"
	,"http://www3.nhk.or.jp/rss/news/cat3.xml"
	,"http://www3.nhk.or.jp/rss/news/cat4.xml"
	,"http://www3.nhk.or.jp/rss/news/cat5.xml"
	,"http://www3.nhk.or.jp/rss/news/cat6.xml"
	,"http://fullrss.net/a/http/rss.asahi.com/rss/asahi/newsheadlines.rdf"
	,"http://fullrss.net/a/http/rss.dailynews.yahoo.co.jp/fc/rss.xml"
	];


	//ニュース取得
	var index=0;
	var getNews = function(){
		var def = $.Deferred();
		var url = feedurl[index++];
		if(index>feedurl.length-1) index=0;
		$("#url").text(url);
		var feed = new google.feeds.Feed(url);
		feed.setNumEntries(10);//取得データ10件に制限
		feed.load(function (result){
			$('#feed').fadeOut(function(){
				$('#feed').children().remove();
				if (!result.error){
					for (var i = 0; i < result.feed.entries.length; i++) {

		var entry = result.feed.entries[i];
		var title = '<li><h3><a href="' + entry.link + '">' + entry.title + '</a></h3></li>';
		var conte = '<li>' + entry.content + '</li>';
		var dates = '<li>' + entry.publishedDate + '</li>';
		$('#feed').append('<li class="post"><ul>' + title + conte + dates + '</ul></li>');

					}
					$('#feed').fadeIn(function(){def.resolve();});
				}else{
					$('#feed').fadeIn(function(){
						$('#feed').append('<li class="post">' + result.error.code+":"+result.error.message + '</li>');
						def.reject();
					});
				}
			});

		});
		return def.promise();
	}
	
	//ループ実行	
	var loop = function(){
		var wait = function(){
			var def2 = $.Deferred();
			setTimeout(function(){def2.resolve();},5*1000);
			return def2.promise();
		}
		getNews().then(wait).then(loop);
	}
	loop();
	
	
}
google.setOnLoadCallback(initialize);
</script>

</head>
<body>
<h3>Demo</h3>
<p id="url"></p>
<ul id="feed">
</ul>



Demo

住所から郵便番号変換のメモ

ricollab 郵便番号検索」を利用すれば、
簡単なんで説明はありません。

ricollabさんありがとう
では、demoどうぞ
住所郵便番号変換

//=================================
//	明細作成
//=================================
    $(function () {
        var ResponseSet = function (data, status) {

            $("#ul_ZipList").html("");

            if (data.totalResults==0){
                $("#lbl_ZipCode").text("データがありません");
            }else{
            $("#lbl_ZipCode").html("query:" + data.query
                + "<br>totalResults:" + data.totalResults
                + "<br>itemsPerPage:" + data.itemsPerPage
                + "<br>next:" + data.next
                + "<br>prev:" + data.prev);
            }

            if (data.itemsPerPage != 0) {
                $.each(data.result, function (i, item) {
                    var j = "{zipcode:\"" + item.zipcode + "\",address:\"" + item.address + "\"}";
                    $("#ul_ZipList").append("<li><input type='button' class='cmdSLT' value='" + item.zipcode + "'><input type='hidden' value='" + j + "'>&nbsp;" + item.address + "</li>");
                });
                var mov = "";
                if (data.prev != undefined) {
                    mov += "<input type='button' class='cmdMOV' value='戻る'><input type='hidden' value='" + data.prev + "'>";
                }
                if (data.next != undefined) {
                    if (mov != "") mov += "&nbsp;";
                    mov += "<input type='button' class='cmdMOV' value='次へ'><input type='hidden' value='" + data.next + "'>";
                }
                if (mov != "") {
                    $("#ul_ZipList").append("<li>" + mov + "</li>");
                }
            }
        }
//=================================
//	明細ボタンクリック
//=================================
        $(".cmdSLT").live("click", function () {
           alert(this.nextSibling.value);
        });
//=================================
//	移動ボタンクリック
//=================================
        $(".cmdMOV").live("click", function () {
            $.getJSON(this.nextSibling.value + "&callback=?"
            , null
            , ResponseSet
            );

        });
//=================================
//	実行ボタンクリック
//=================================
        $("#cmdEXE").click(function () {
            $.getJSON("http://zip.ricollab.jp/search?callback=?"
            , { q: $("#txt_Address").val(), type: "json" }
            , ResponseSet
            );

        });

    });

Enter/Tab項目移動とFunctionKey制御をplugin化


Enter/Tab項目移動とFunctionKey制御 jqKeyプラグイン更新 - せかにゃ~
以下の内容は古くなりましたので、上記記事を参照してください。

一つにまとめてみました。

以前作成したものは、一部間違ってるかも。こちらを参照してください。


機能
  • Enter、Tabでのフォーム移動
  • Functionキー制御・・・・・・Fキー押下時の関数登録可能です。
  • [BackSpace]キーでのページ遷移抑制
OPTION
Enter true/false
Tab true/false
F1〜F12,ESC function(object,shiftKey,ctrlKey,altKey){}
object キー押下時のオブジェクト
shiftKey shiftKeyの状態:true/false
trlKey ctrlKeyの状態:true/false
altKey altkeyの状態:true/false
jqKey.js SourceCode jQuery:1.4.3以上 ファイル名:jqKey.js
(function($){
	$.fn.jqKey = function(options){
		window.onhelp=function(){return false;}
		var defaults = {
			"Enter":false
			,"Tab":false
			,"F1":null
			,"F2":null
			,"F3":null
			,"F4":null
			,"F5":null
			,"F6":null
			,"F7":null
			,"F8":null
			,"F9":null
			,"F10":null
			,"F11":null
			,"F12":null
			,"ESC":null
		};
		var setting = $.extend(defaults,options);
		var method = function(e){

			var Focus_Move = function(df,shift){
				//フォームオブジェクトが何番目か探す
				var ln = df.length;
				var i;
				for (i=0;i<ln;i++){
					if (df[i]==obj) break;
				}
				//フォーカスを取得できないものは飛ばします
				var mv = (shift?-1:1);
				var j = (ln+i+mv) % ln;
				var Fo,Fs;
				while(true){

					Fo	=	df[j];
					Fs	=	Fo.style;
					if	(Fo.type!="hidden" &&
						Fo.style.visibility!="hidden" &&
						!Fo.disabled &&
						Fo.tabIndex!=-1 &&
						Fs.visibility!="hidden" &&
						Fs.display!="none"){
						//対象のオブジェクトを戻す
						return Fo;
					}
					j=(j+mv+ln) % ln;
				}
				//Hitしない場合
				return df[i];
			}
			var df = document.forms[0];
			var	k	=	e.keyCode;
			var	s	=	e.shiftKey;
			var	c	=	e.ctrlKey;
			var	a	=	e.altKey;
			var	obj	=	e.target;
			var blKey	=	true;
			if (!setting.Enter&&k==13) return true;
			if (!setting.Tab&&k==9) return true;
			switch(k){
				case 13:
					switch(obj.type){
					case"button":
					case"file":case"textarea":
						blKey = true;
						break;
					case"radio":case"checkbox":
//						setTimeout(function(){obj.click();},1)
//						blKey = true;
//						break;
					case"text":case"select-one":case"select-multiple":
						blKey = false;
						break;
					default:
						blKey = false;
						break;
					}
					//keyイベントを処理するもののみ抽出
					if (!blKey){
						//次のフォームオブジェクト探す
						obj = Focus_Move(df,s);
					}
				break;
				case 9:		//tab
					switch(obj.type){
					case"file":
						blKey = true;
						break;
					default:
						//次のフォームオブジェクト探す
						obj = Focus_Move(df,s);
						blKey = false;
						break;
					}

				break;
				case 8:		//backspace
					switch(obj.type){
					case"text":case"textarea":
						blKey = true;
						break;
					default:
						if(confirm("backspaceが押されました。\n前ページへ移動しますか?")){
							blKey = true;
						}else{
							blKey = false;
						}
						break;
					}

				break;
				case 27://ESC
					if(setting.ESC){
						setting.ESC();
						blKey = false;
					}
				break;
				default:
					if(k>=112&&k<=123){
						var F = setting["F"+(k-111)];
						if(F)F(obj,s,c,a);
						blKey = false;
					}
				break;
			}



			if(!blKey){
				//イベントを伝播しない
				//IE規定の動作キャンセル
				if(document.all) window.event.keyCode = 0;
				obj.focus();
				if(obj.select&&obj.type!="button") obj.select();
			}
			return blKey;
		};

        this.each(function() {
			$(this).keydown(function(e){
				var ret =method(e);
				return ret;
			});
		});
	}
})(jQuery);

使い方
$(document).jqKey(
{
	Enter:true               //Enterで次項目移動する
	,Tab:true                //Tabで次項目移動する
	,F1:function(object,shiftKey,ctrlKey,altKey)
	{alert("push F1 key\n shift:"+shiftKey+"\nctrl:"+ctrlKey+"\n:alt:"+altKey);}
	//F1キー押下時の関数登録
	,ESC:function(){alert("push ESC key");}//ESCキー押下時の関数登録
});
動作サンプルWinのfirefox3.6,IE8のみ確認 [Fキー]や[Enetr][Tab]を押して動作確認してください。 Shift,Ctrl,Altを押しながらの操作にも対応しています。 ご自由に改造して使ってください

「CGIが動かない」で嵌った

現在Vine3.1からCentOS5.4へ環境移行を行ってたのですが、「CGIが動かない」現象で嵌ったのでその時のメモ

結論から言うと、centOSのvsftpd(FTPサーバ)の設定にてasciiコードの送受信を許可してなかったからでした。

まずはエラーの状況説明
http.confにてAddDefaultCharsetをUTF-8→noneに設定
cgiパーミッションを正確に設定したのにブラウザからは以下のエラー

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, hide@hidenet.ath.cx and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.
Apache/2.2.3 (CentOS) Server at 192.168.1.XXX Port 80

apacheのエラーログは、

[Thu Feb 11 19:04:57 2010] [error] [client 192.168.1.XXX] (2)No such file or directory: exec of '/home/*******/public_html/cgi-bin/****.cgi' failed
[Thu Feb 11 19:04:57 2010] [error] [client 192.168.1.XXX] Premature end of script headers: ****.cgi


調べてみるとこの辺がヒントらしきものが・・・
http://d.hatena.ne.jp/otn/20090818/p1
cgiの先頭行を
#!/usr/bin/perl --←追加
でも正常に動作するようになりますが、民間療法らしいです。

そこで更に原因究明に探すと・・・
http://sakaguch.com/PastBBS/0032/B0016504.html

どやら、FTPサーバの設定が間違ってたらしい。(デフォルトのまま使ってた)

対策は以下の通り
viで /etc/vsftpd.conf を編集

以下の項目に移動
# ASCII mangling is a horrible feature of the protocol.
#ascii_upload_enable=NO
↓変更
ascii_upload_enable=YES
#ascii_download_enable=NO
↓変更
ascii_download_enable=YES

保存して、再起動
# /etc/init.d/vsftpd restart

で、FTPでコンテンツを再送信でOKでした。

jQueryのEnterでカーソル移動って...


Enter/Tab項目移動とFunctionKey制御 jqKeyプラグイン更新 - せかにゃ~
内容が古くなりましたので、上記記事をさんしょうしてください。

前回べた書きしましたが、プラグイン化で整理しました。

[http://hidenet.ath.cx/jqEnterTab.js:title=jqEnterTab.js SourceCode]
$.extend($.fn,{
	EnterTab:function(o){

		var Focus_Move = function(df,i,ln,shift){
			//フォーカスを取得できないものは飛ばします
			var mv;
			if (shift){
				mv	= -1;
			}else{
				mv	= 1;
			}
			var j = (i+mv) % ln;
			var Fo,Fs;
			while(i=j){
				
				Fo	=	df[j];
				Fs	=	Fo.style;
				if	(Fo.type!="hidden" &&
					!Fo.disabled &&
					Fo.tabIndex!=-1 &&
					Fs.visibility!="hidden" &&
					Fs.display!="none"){
					//対象のオブジェクトを戻す
					return Fo;
				}
				j=(j+mv) % ln;
			}
			//Hitしない場合
			return df[i];
		}
		var d = document;
		var $input = $(":input",this)
		$input.keydown(function(e){
			var	k	=	e.keyCode;
			var	s	=	e.shiftKey;
			var	obj	=	e.target;
			var blKey	=	true;
			if (!o.Enter && k==13) return true;
			if (!o.Tab && k==9) return true;

			if (k == 13 ||k == 9){
			//Enter tabによるフォーカス移動
				switch(obj.tagName){
				case "TEXTAREA":
					if (k!=13) blKey = false;
					break;
				case "INPUT":	case "SELECT":
					//fileは巧く動かないので除外
					if (obj.type!="file")	blKey = false;
					break;
				default:
				}
				//keyイベントを処理するもののみ抽出
				if (!blKey){
					//フォームオブジェクトが何番目か探す
					var ln = $input.length-1;
					var i;
					for (i=0;i<ln;i++){
						if ($input[i]==obj) break;
					}
					//次のフォームオブジェクト探す
					obj = Focus_Move($input,i,ln,s);
				}
			}

			if (!blKey){
				//イベントを伝播しない
				if (obj.type!="file"){
					//IE規定の動作キャンセル
					if(d.all) window.event.keyCode = 0;
					obj.focus();
					if (obj.select && obj.type!="button") obj.select();
				}else{
					blKey = true;
				}
			}
			return blKey;
		});
	}
});
2010/2/26jqEnterTabちょっと修正 使い方
$(function(){
	$(document).EnterTab({Enter:true,Tab:true});
	
	//初期Focus設定
	document.forms[0][0].focus();
});
動作サンプルWinのIE8とFirefox3.5のみ確認 [Enetr][Tab]を押して動作確認してください。 Shiftを押しながらの操作にも対応しています。 ご自由に改造して使ってください