<

![endif]-->

fc2ブログ

mirrorMan - お気に入り機能2

2はソースです。
<span id=setLstArea></span>
<script>
setLstArea.innerHTML ="<ul id=setLstBar></ul>";
var ar = (new VBArray(dicIniLft.Keys())).toArray();
for(var i in ar) $(setLstBar).append("<li><a href=# class=setLstBtn>"+
"<span id="+ ar[i] +" class=setLstSpn>"+
ar[i].replace(/^f_/,"") +"</span></a></li>");
$(setLstBar).sortable({revert:true});
$('#'+ar[0]).css("color","limegreen");
</script>
jquery.uiのsortableはver1.5あたりからマウスを離した後にずりずりっと元の位置に戻るアニメーションがデフォルトでオフに変わっていますが、revert:trueオプションを指定することでオンになります。
お気に入りを追加するのはこんな感じです。
var btnNm = prompt("名前を入力してください。","");
if((btnNm == null)||(!btnNm)) return;
else btnNm = btnNm.replace(/^(\s+)(.+)/,"$2");
if(dicIniLft.Exists("f_"+ btnNm))
return wsh.popup("同じ名前のボタンが既にあります。",0,document.title,64);
if(/[\\\/:\*\?"'<>\|,;@{}\[\]()$$]/.test(btnNm)) //"
return wsh.popup(
"ボタン名に次の文字は使えません。\n\n"+
" \\ / : @ * ? $ \" \' <> | , {} [] ()",0,document.title,64);
$(setLstBar).append("<li><a href=# class=setLstBtn>"+
"<span id=f_"+btnNm+
" class=setLstSpn style=display:none>"+
btnNm+"</span></a></li>");
dicIniLft.Add("f_"+ btnNm,getAdrBar(0));
dicIniRht.Add("f_"+ btnNm,getAdrBar(2));
setLstBtnClear();
$('#f_'+ btnNm).css('color','limegreen');
if(/MSIE 6/.test(navigator.appVersion)) $('#f_'+btnNm).show();
else $('#f_'+btnNm).fadeIn("slow");
$(setLstBar).sortable("refresh");

ボタン名、つまりお気に入り名はdictionaryのKeyとして格納するので、
文字列のチェックが必要です。
まず先頭の空白があれば取り除きます。
同じKeyがあるか、使えない文字はないかを判定し、登録します。
その後の処理、jQueryは便利です。
ただ、IE6だとfadeIn()がうまく動作しないようなので、show()を使用しています。
並べ替えを可能にするには、これが実にsortable({})と書くだけです。すごい。

あと、マウスポインタが上にきたときのmouseoverイベントで背景画像を変えるのは、
Sliding Doorテクニックという、javascriptも使用しないなつかしい方法を使っています。sliding Doorとは引き戸のことですが、横に長い画像を文字列幅で切り詰めつつ、右どなりの要素には右端の画像を使うという方法です。ちょうど引き戸を閉めて壁に隠れていくイメージですね。これによって、長さの異なる文字列で登録されるお気に入りであっても、マウスが重なるとその範囲をフォーカス表示しています。



mirrorMan - お気に入り機能

このソフト最大のメリット、お気に入りボタンについてです。
初めて起動すると、「サンプル1」というボタンが表示され、
左ペインにマイドキュメント、右ペインにデスクトップが表示されます。




さっそく登録してみます。
保存したいフォルダのペアを左右ペインに表示させたら、
右クリックして「この状態を登録」を選択します。



プロンプトが表示されるので、登録したい名前を入力します。「新オキニ」と入力しました。


「新オキニ」が表示されました。
これでいつでも「新オキニ」のワンクリックで登録したフォルダのペアにアクセスできます。




「サンプル1」はもういらないので削除します。
カーソルを合わせて右クリックし、「削除」を選択します。




「サンプル1」が削除されて表示されなくなりました。




どんどん登録していきます。
クリックして表示したお気に入りの文字は緑色になります。



マウスでぐりぐりドラッグして順序を並べ替えられます。jQueryのSortableありがとう。



お気に入りは、終了時の状態が次回起動時にも表示されます。

慣れてくれば、mirrorManを起動したらファイルをサーバからコピーして開き、保存して赤い矢印ボタンでコピーという一連の作業がだいぶ楽だと思います。





mirrorMan - 一括コピーボタン2

2ではソースの抜粋です。
mirrorManはOSのファイルシステムとリアルタイムにリンクしていません。ファイルを色分けしして画面表示してから、一括コピーボタンが押下されるまでの間にファイルが更新されている可能性があります。これをキャッチしないとたとえば次のようなことが起きかねません。
・サーバの共有ファイルが「俺が更新したのに何で古いファイルをまた上書きしてんだよ」なんて非難されてしまう。
・自分がローカルで更新したのを忘れて、うっかりサーバから上書きしてしまい、既に脳内キャッシュ領域からも消去されてしまった作業が露と消えてしまう。

そういうわけで、以下の8つのケースをコピー時にチェックしています。前回で確認ダイアログはバカだといいつつ、そういうファイルが見つかるたびにダイアログを表示して問い合わせます。

■赤いファイルのコピー時
1.赤いファイルの更新日時をコピー時にも比較する。
2.赤いファイルがコピー先に存在しない。
3.赤いファイルがコピー先のほうが新しい。
4.赤くないファイルがコピー先よりも新しい。
5.画面に表示されていないがコピー先より新しいファイルが存在した。

■青いファイルのコピー時
1.青いファイルがコピー先に存在する。
2.青くないファイルがコピー先に存在しない。
3.画面に表示されていないがコピー先に存在しないファイルが存在した。

ソースは長ったらしく、自分で見るのもちょっといやです。
役所で窓口をたらい回しにされるような気分になります。
function copyColoredFile(elmid){
var lftFol = getFolderSub(getAdrBar(0));
var rhtFol = getFolderSub(getAdrBar(2));
if(/Rht/.test(elmid)){
var objErFol = sfs.GetFolder(lftFol);
var strErFol = lftFol, strEdFol = rhtFol, strEr ="Lft";
}else{
var objErFol = sfs.GetFolder(rhtFol);
var strErFol = rhtFol, strEdFol = lftFol, strEr ="Rht";
}
var cItm,edDLM,erDLM,erItm,fcItm,intBt,itmNm,tFol;
var clr = /red/.test(elmid);
var itms = document.getElementsByTagName('PRE');
パラメータはボタンのid属性です。左右ペインのアドレスバーの値からフォルダオブジェクト、他にパス、ボタン色などを取得しています。
  for(var i in itms){
if(!itms[i].className) continue;
if((clr)&&(itms[i].className.split(" ",1)[0] =="fNmRed"+strEr)){
itmNm = itms[i].innerText;
erItm = sfs.GetFile(sfs.BuildPath(objErFol,itmNm));
if(! sfs.FileExists(sfs.BuildPath(strEdFol,itmNm))){
intBt = wsh.popup("赤いファイル "+itmNm+" がコピー先に存在しません。\n"+
"このファイルのコピーを行いますか?",0,document.title,36);
if(intBt == 7) continue;
}else{
erDLM = new Date(erItm.DateLastModified);
edDLM = new Date(sfs.GetFile(sfs.BuildPath(strEdFol, itmNm)).DateLastModified);
if(erDLM < edDLM){
wsh.popup("赤いファイル "+itmNm+"\n\nコピー先のほうが新しくなっています。"+
"\nコピーを中止します。\n\n"+
"コピー元更新日時: "+ erDLM.toLocaleString() +"\n"+
"コピー先更新日時: "+ edDLM.toLocaleString() ,0,document.title,48);
loadItms(1);
return;
}
}
tFol = ssh.NameSpace(strEdFol);
cItm = ssh.NameSpace(strErFol).ParseName(itmNm);
tFol.CopyHere(cItm, sshCpyOpt);
コピペしたら説明するモチベーションが潰えました。要は最後から2行目でCopyHere()しているというわけです。オプションパラメタのsshCpyOptの設定値(>MSDN)は、INIファイルの[cpyOpt]の値で好みで変更できます。デフォルトは80です。

    }else if((!clr)&&(itms[i].className.split(" ",1)[0] =="fNmBle"+strEr)){
itmNm = itms[i].innerText;
erItm = sfs.GetFile(sfs.BuildPath(objErFol,itmNm));
if(sfs.FileExists(sfs.BuildPath(strEdFol,itmNm))){
erDLM = new Date(erItm.DateLastModified);
edDLM = new Date(sfs.GetFile(sfs.BuildPath(strEdFol, itmNm)).DateLastModified);
intBt = wsh.popup("青いファイル "+itmNm+"\n\nコピー先に存在します。\n"+
"このファイルの上書きコピーを行いますか?\n\n"+
"コピー元更新日時: "+erDLM.toLocaleString() +"\n"+
"コピー先更新日時: "+edDLM.toLocaleString() ,0,document.title,36);
if(intBt == 7) return loadItms(1);
}
tFol = ssh.NameSpace(strEdFol);
cItm = ssh.NameSpace(strErFol).ParseName(itmNm);
tFol.CopyHere(cItm, sshCpyOpt);
}
}
要は最後から2行目でCopyHere()しているというわけです。
  for(var i=0,fcer=new Enumerator(objErFol.files); !fcer.atEnd(); fcer.moveNext(),i++){
fcItm = fcer.item().Name;
if((clr)&&(sfs.FileExists(sfs.BuildPath(strEdFol, fcItm)))){
erDLM = new Date(fcer.item().DateLastModified);
edDLM = new Date(sfs.GetFile(sfs.BuildPath(strEdFol, fcItm)).DateLastModified);
if(erDLM > edDLM){
intBt = wsh.popup("赤い表示ではないファイル\n\n"+fcItm+"\n\nコピー先より新しくなっています。\n"+
"このファイルの上書きコピーを行いますか?\n\n"+
"コピー元更新日時: "+erDLM.toLocaleString() +"\n"+
"コピー先更新日時: "+edDLM.toLocaleString() ,0,document.title,36);
if(intBt == 7) continue;
tFol = ssh.NameSpace(strEdFol);
cItm = ssh.NameSpace(strErFol).ParseName(fcItm);
tFol.CopyHere(cItm, sshCpyOpt);
}
}else if((!clr)&&(!sfs.FileExists(sfs.BuildPath(strEdFol,fcItm)))){
intBt = wsh.popup("青い表示ではないファイル "+fcItm+"\n\nコピー先に存在しません。\n"+
"このファイルのコピーを行いますか?",0,document.title,36);
if(intBt == 7) continue;
tFol = ssh.NameSpace(strEdFol);
cItm = ssh.NameSpace(sfs.GetParentFolderName(fcer.item())).ParseName(sfs.GetFileName(fcItm));
tFol.CopyHere(cItm, sshCpyOpt);
}
}
setTimeout('loadItms(1)',0);
}
コピー対象の色ではないファイルがその配色と同じ状態だった場合を探すために、もう一度ループします。今度はファイル名の色は必要ないので、フォルダオブジェクトのコレクションで全てのファイルにアクセスします。画面に表示されていないファイルをここでキャッチします。要は最後から2行目でCopyHere()しているというわけです。



『カラマーゾフの兄弟 3』@北の丸公園


もはや大人買いの自己責任を取るために通勤電車の暇つぶしと化しているのだが、17時からBSMのデイバッグに『カラマーゾフの兄弟 3』を放り込んで皇居北の丸公園へ。日が傾いて人も少なく風が気持ちいい。涼しいものの、蚊も運んでくるので30分おきにセブンスター蚊取り線香に火をつけつつ、パチンと殺す。地面のアリがそそくさと撤去していく。自分の血がアリの巣に運ばれていくのもアヤシイ気分がする。

前を通り過ぎる観光客らしき白人グループが自転車をじろじろ見ていく。こっちはくわえタバコで対蚊戦中で、意味もなく喫煙者の肩身の狭い気分になる。そのスキをみて敵機は爆音とともに耳の穴に急降下ダイブをかましてくる。目を本に落とせばあーでもないこーでもないと嫉妬だの金だのの屁理屈をこねまわす登場人物たち。

あーもう。

ドSノエフスキー全部おまえのせいだ!


mirrorMan - 一括コピーボタン

ファイルやフォルダをドラッグ&ドロップすることでコピーや移動を普通にすることもできますが、
2ペイン型ならではの機能としてファイルの一括コピー機能があります。
赤と青の矢印ボタンがそれです。



同じ名前のファイルの更新日時を比較しています。
ファイル名の色分けは次のとおりです。

赤 :もう一方のペインよりも新しいファイル
赤紫 :もう一方のペインよりも古いファイル
青 :片方にしかないファイル



灰色: 更新日時も同一のファイルです。

この画面の場合は青いファイルを右ペインにコピーするだけなので、青の右矢印ボタンだけが表示されています。今回はこのボタン表示をグレイアウトさせるのではなく、表示されないように変更しました。



青い右矢印ボタンを押した結果の状態です。
青いファイルが右側にコピーされて、更新日時が同一なので灰色になりました。
青い右矢印ボタンも表示されなくなりました。

同様の動作を赤いボタンでも上書きコピーで行います。



矢印ボタンが4つとも表示されている最初の画面で赤い右矢印ボタンを押した結果です。
2_名無し.txtファイルだけが右にコピーされて灰色になり、赤右矢印ボタンも表示されなくなりました。

上書きコピーの場合、エクスプローラではいちいち確認ダイアログボックスが表示されますね。
そんなことはしません。
ダイアログに目を通すのがわずらわしくてろくに目を通さずにクリックするくせに、ダイアログが表示されるからと安心してしまっているから誤って間違いコピーをしてしまうのです(私の場合)。ユーザに確認を求めるポップアップ表示なんてものは、慎重性と習慣性の無限ループです(私にとっては)。
考える前にファイル名が赤ければいいのだと()。

4つのボタンを使い分けることで、パターン別にファイルのミラーリングが行えます。
また、ファイルの色づけ、ボタンの表示/非表示はフォルダを移動する度に行うので、
該当のファイルがあるかどうかは、ボタンが表示されているかどうかで一目でわかります。

ソースの紹介は次回に。


mirrorMan - コンボボックス風フォーム2

2ではソースの抜粋です。

右クリックメニューを表示するプラグインを読み込みます。
<script type="text/javascript" src="jquery.contextmenu.r2.packed.js" defer></script>

アドレスバー領域の要素です。
<span id=LftPthLst></span><span id=LftPthBox></span>

メニュー内容を作成します。class属性の指定で、プラグインによって起動後には非表示になります。
<div class="contextMenu" id="conMenuToAddBar">
<ul>
<li id="pasteToAddBar">貼り付け</li>
<li id="cpoyFrmAddBar">コピー  </li>
</ul>
</div>
右クリックメニュー項目選択時の処理です。色分けしたid属性値がひもづいています。
$('#LftPthLst').contextMenu('conMenuToAddBar',{
bindings:{
'pasteToAddBar': function(t){
switchPathBoxBtn(LftPthBox, clipboardData.getData("Text"));
},
'cpoyFrmAddBar': function(t){
clipboardData.setData("Text", LftPuldwn.options[LftPuldwn.options.selectedIndex].value);
}
}
});

function loadAdrBarItms(num,flg){
var resv = (new RegExp).compile(/^(\\\\.+\\)(.+?\\)/);
var relo = (new RegExp).compile(/^([A-Z]:\\).+(\\.+?)(\\.+?\\)/);
if(flg < 2){
var lHTML ="<select id=LftPuldwn class=lst0 onChange=chgLst(this.options[this.options.selectedIndex].value,0)>";
var itm,arLft = (new VBArray(dicLstLft.Keys())).toArray();
for(var i in arLft){
itm = String(dicLstLft(arLft[i]));
lHTML +="<option id='"+ arLft[i] +"' value='"+itm+"'>"+itm.replace(resv,'\\\\..\\$2').replace(relo,'$1..$3');
} lHTML +="</select>";
LftPthLst.innerHTML = lHTML;
var elm = document.all[arLft[num]];
elm.selected = true;
LftPthBox.innerHTML ="<input type=text class=txt0 id=LPthTxtBox value='"+ elm.value +"'>";
LPthTxtBox.size = (new String(elm.value)).length;
}
if(flg > 0){
var rHTML ="<select id=RhtPuldwn class=lst2 onChange=chgLst(this.options[this.options.selectedIndex].value,2)>";
var itm,arRht = (new VBArray(dicLstRht.Keys())).toArray();
for(var i in arRht){
itm = String(dicLstRht(arRht[i]));
rHTML +="<option id='"+ arRht[i] +"' value='"+itm+"'>"+itm.replace(resv,'\\\\..\\$2').replace(relo,'$1..$3');
} rHTML +="</select>";
RhtPthLst.innerHTML = rHTML;
var elm = document.all[arRht[num]];
elm.selected = true;
RhtPthBox.innerHTML = "<input type=text class=txt2 id=RPthTxtBox value='"+ elm.value +"'>";
RPthTxtBox.size = (new String(elm.value)).length;
}
}
プルダウンリストとテキストボックスの両方のhtmlを記述しています。とくにモダンなことはしていません。仕事場なんかだと長いフォルダ名や深い階層が多いので、パスを省略表示するための正規表現をfor文の中で何回も(リストの項目数分)使用するので、あらかじめ内部形式にコンパイルしているくらいでしょうか。あとは、パラメータ変数flgは左ペインなら0、右ペインなら2、両方なら1という値で左右の処理の有無を分けています。テキストボックスの幅は、文字数から求めています。
$(LftPthBox).toggle();
起動時はプルダウンリストのみを表示するので、テキストボックスを格納するspan要素はtoggle()メソッドで非表示にします。
function switchPathBoxBtn(elm, clp){
if(/^L/.test(elm.id)){
var box=LftPthBox, tox=LPthTxtBox, lst=LftPthLst, dwn=LftPuldwn;
}else{
var box=RhtPthBox, tox=RPthTxtBox, lst=RhtPthLst, dwn=RhtPuldwn;
}
if(box.style.display == "inline"){
box.style.display ="none";
lst.style.display ="inline";
}else{
box.style.display ="inline";
tox.value = clp || dwn.options[dwn.options.selectedIndex].value;
tox.width = lst.offsetWidth;
lst.style.display ="none";
txtBoxFocus(tox);
}
try{ resizeTo(currentWindowSize.width,currentWindowSize.height) }catch(e){}
winPositionize();
}
プルダウンリストとテキストボックスを切り替えるメインです。上で使っているjQueryのtoggle()を使えばいいかとも思いますが、toggle()はvisibiltyで切り替えているのでノードオブジェクト自体は消されません。起動時はむしろこっちのほうが安全ですが、displayプロパティならノードオブジェクトも消えるので、自前でやるならこっちのほうが安定するという意図です。
左ペインの処理か右ペインかでhtmlノードオブジェクトをそれぞれひとつの変数に格納して、displayプロパティを切り替えます。
テキストボックスの値は、右クリックメニューで貼り付けを選択された場合にパラメータでクリップボードデータが渡されていればそれを、なければプルダウンリストで選択されている値です。最後の2行は、画面の位置とサイズを調整する呼び出しです。HTAの場合、resizeTo()処理時にマウスのボタンが押されたままの状態だとエラーになるので、try{}catch{}で逃がします。

「 HTMLでコンボボックス風に マウス長押しで切替えてみる」も。



Capreoリアハブ グリスアップ

BSMの走行距離が1000kmを超え、スプロケの掃除をした時に洗浄剤のスプレーをかけすぎてしまい、ハブフリー部からラチェット音がするようになってしまっていたので、グリスアップをかねて分解。

ロックリングはcapreo専用工具のTL-HG09で下図のようにゆるめます。↓

ロー側4枚はカシメてあるのでここを削らないと分解はできません。しかしこういうのは心くすぐるパーツですね。
←ボールベアリング部、思ったほどグリスがついてません。グリスで埋め尽くすのを10割として、一般には7~8割といわれますが、メーカの出荷状態ってこんなものなんでしょうか。そーっと起こしてカメラを向けましたが、すでに一つボールが落っこちてました。こんなときにはピンセットですが、用意し忘れてました。

←ハブ側ボール受け部は、とくに研磨されてません。これがCapreoハブはゴリゴリするといわれる理由の箇所でしょうか。

→ボールは片側9個づつ。球面の反射で傷を探すのも目が回りそうです。これが左右前後の計12個くらいで自転車と人間を支えて高速回転しているのかと思うと、なんともきれいなものです。ポトッと落して失くしたこと、バイクで何度かありました。コマ送り写真のように転がって四次元の彼方へ消えていきます。


←軸側のボール受けは接触面に白い筋ができています。ちょうど研磨された感じでしょうか。傷も凹凸もなく、グリスをきれいにふき取ります。
→そして肝心の、ラチェット音を確認したいフリーボディ。10mmの六角レンチで外します。こんな工具バイクでもクルマでも見たことありません。つっこんで回します。極太レンチですが、タイヤをつかんで回せば、体重をかけることもなく外れました。



←左の銃の薬きょうみたいなのが、10mmレンチを受けてフリーボディをハブに固定しているボルトです。そして双方の大きなギザギザがフリーとハブをかみ合わせている部分で、
まんべんなくグリスがついています。
上の黒い方のギザギザに爪をひっかけて回すと、
チリチリとラチェット音が聞こえます。ようやくたどりつきました。







はて、ラチェット音を消すグリスはどこにすればいいのでしょう。どこにも見当たりません。SHIMANOサイトの、CapreoドライブシステムのPDFマニュアルを当たってみます。

がーん!

なんじゃこりゃー、ヅマノ!
洗浄剤が入り込んだ箇所かと思われるすきまに空しくグリスをすりこんでみますが、本来簡単に入ってはいけないすきま、ラチェット音が消えることもありません。それでも、回転がしぶくなることもいとわず、ズラ油だくだく盛りで組み戻しました。ちゃんちゃん。

続:
コメントをもらってちょっと調べました。シマノ純正で「フリーボディグリス」という専用のものがありました。フリーボディはラチェットの接触上、高温になる部品だそうで、それへの対応と、かつ粘度も低くなっているようです。でもバラさないと使えないかな。

それから、『ロードバイクの科学』誌にもデュラグリスについて記載がありました。グリスといってもオイルはオイルで、それが微細なカプセルに詰まっていて、磨耗で少しずつつぶしながら使うことで流れ落ちないようになっているとか。つまり、時間が経過して少しづつ漏れ出しているように見えるのは、本来の潤滑の役割をし終えたオイルが出てきているというわけだそうです。

組み付け後、メンテ台にのせてくるくる回していたら、ラチェット音は耳を近付けないと聞こえないくらい小さくなってしまいました。あのすき間は、そこからスプレーグリスを吹き入れる人もあるようで、たっぷり塗ったのがしみ込んだかと思われます。ただ、ペダルを勢いよく回すと、手を離してもクランクがしばらく回り続けてしまうように。クルマのAT車で停車中にブレーキを離すとクラッチオイルの抵抗でスルスル進みますが、ちょうどそんな感じか。




mirrorMan - インクリメンタルサーチ

エクスプローラのフォルダウインドウでファイル名をタイプすると、その文字にマッチするファイルにフォーカスが移ります。「m」と入力するとファイル名の頭に「m」がついているファイル、続けて「irr」と入力すると「mirr」がついているファイルという具合に、連続したキー入力でフォーカスが移動していくのを目で確認しながら、目的のファイルを探し出すことができます。
FFFTPでサーバの大量ファイルを探すときにはおなじみの機能で、Vistaでも検索ウインドウやスタートメニューのファイル名を指定して実行などで取り入れられています。たとえばエクセルを使うなら、ウインドウズキーを押してexcelと入力すれば最近使ったエクセルファイルがすぱっと一覧で表示されるので、UIとしては最短距離ではないでしょうか。PCのアイドル時にひたすらカリカリとインデックスを作成しているだけあります。評判が悪いというか地に堕ちたVistaですが、検索機能は職場でも使いたいです。元々Mac派でWindows95のときは憎しみすら覚えたクチなんですが、ごく短い期間ですがMSで働いたこともあって、今はWindowsに同情する側です。

ソースの該当部分ですが、まず、
document.body.onkeydown = handleKeydown;
onkeydownをhandleKeydownにオーバーライドします。参照ではないので、()は付けません。


function handleKeydown(){
var ky = event.keyCode;
var shKy = event.shiftKey, ctKy = event.ctrlKey, alKy = event.altKey;
if((!ctKy)&&(!shKy)&&(!alKy))
if(((ky>=48)&&(ky<=57)) || ((ky>=65)&&(ky<=90)) || ((ky>=97)&&(ky<=111)))
return selItmByKeyDown(ky);
}
Shiftキーや、Ctrlキー、Altキーの押下状態は、IEの場合トップレベルのeventオブジェクトにあります。
これらのキーが押されている場合をまず除外します。さらに、0-9、A-Z、a-zの範囲だった場合に処理を行います(テンキーの0-9は別のkeyCodeですが対応していません)。onkeydownにかぶせる処理はここまでです。

次に画面の動きです。

たとえば「qwef」と入力すると、

1.3秒間、このようにキー入力をプールした状態を表示します。1.3秒間は入力追加とし、最初に入力したキーからそれ以上経過するとクリアします。そして、ここに表示している文字列をもとにファイル名の検索を行います。インクリメンタルサーチ入力の閾値が1.3秒で、それ以降は新しい入力だというわけです。短いと入力し切れないし、長いと次の新しい入力を待ってイライラ、とあんばいがムズカシスところです。


「b」をタイプしたタイミングで「bac」フォルダにフォーカスします。続けて「a」をタイプしても、まだ文字はマッチしているので1.3秒間以内であればフォーカスは移りません。さらに「k」をタイプして「bak」となれば「bak」フォルダにフォーカスが移ります。


ソースです。
function clearKeyDownPool(){
if(keyDowns.innerText) keyDowns.innerText ="";
}
setTimeout()で1.3秒後に文字列をクリアする処理を関数で用意します。
文字列を表示しているspanタグはid=keyDownsです。

function selItmByKeyDown(k){
k = String.fromCharCode(k).toLowerCase();
if(k != keyDowns.innerText){
setTimeout('clearKeyDownPool()',1300);
k = keyDowns.innerText += k;
}
var elms = document.getElementsByTagName('PRE');
var t, i = cntSelItmId();
for(; i<elms.length; i++){
t = elms[i].innerText;
if((t.indexOf(k) == 0)||(t.indexOf(k.toUpperCase()) == 0)){
if((i == cntSelItmId())&&(k.length < 2)) continue;
selItmLR.innerText = /Lft/.test(elms[i].id) ? 0 : 2;
cntSelItmId(elms[i].id.replace(/...(\d+)/,'$1'));
selItm(elms[i]);
break;
}
}
}
1行目でkeyCodeを文字にしています。
2~5行目では、同じ文字の入力だった場合をはじいています。なぜなら、たとえばa、a、aと入力された場合は、1.3秒なんて待たずに「a~」という名前のファイルに次々とフォーカスが移るべきだからです。それに、頭から同じ文字が続くファイル名なんてほとんどみたことがありません。
画面上では、4行目でinnerText値の更新を処理し、;でコミットしたタイミングで追加入力している文字列が表示されるはずですね。少なくとも、次のfor文の中でinnerTextを取得する段階ではそうなっていないと動作しません。
6行目以降は、ファイルの一覧から一致する名前を探し出す処理です。
htmlの要素の値として持てる文字列と、ファイル名として持てる文字列とは制限に違いがあるので、ファイル名の表示はpreタグに入れてあります。それをgetElementsByTagName()でノードオブジェクトを取得し、画面に表示されているファイルのすべての名前にアクセスできるようにします。
cntSelItmId()は現在フォーカスされているアイテムをid属性値からたどってファイルオブジェクトを取得するためのインデックス値を格納するための処理で、上の画像の数字部分に表示しています。常に画面に表示しておくことで、グローバル変数としてどこからでもアクセスできること、フォーカスがいまどこにあるのかを見れることが目的です。詳細はここでは省略します。
selItm()は、ファイル名を反転表示させてフォーカスを示す処理です。実際はIEのフォーカスではなくて、textRangeオブジェクトのselect()ですが、これも詳細は省略します。



mirrorMan - コンボボックス風フォーム

comboboxとは、プルダウンメニューとテキスト入力ボックスとがコンボ化したフォーム。
アプリケーションでは一般的ですが、HTMLフォームにはありません。
jQueryのUIライブラリにはコンボボックス部品があり、色々試してみましたが、思うように動作するものがありませんでした。そこでIE標準フォームを使ってそれ風のものを作っています。

IE7では、selectタグがondblclickイベントを受け付けられるようになっています。

アドレスバー領域をダブルクリックすると、




テキストボックスに切り替わります。Ctlr+Vでパスを貼りつけたり、直接入力することができます。




IE6の場合、右の移動ボタンを押すか、もしくはプルダウンリストを右クリックして出るメニューから「貼り付け」を選択してテキストボックスへの切り替えます。




あるいはまだ存在しないフォルダを追加入力してEnterキーを押すと、フォルダを作成するかどうかのダイアログが表示されて、

そのフォルダに移動します。
作成したフォルダに移動まで行うのは少し押し付けがましいかもしれませんが、自分ではこれが便利です。
エクスプローラの、右クリックでフォルダを作成してそのフォルダを名前変更して開く、という作業よりは手数が少なくて済みます。

とはいえ、手に染みついたエクスプローラのこの機械作業、やっぱり同じ方法でフォルダを作ることが多いです。











右クリックメニューから「新規フォルダ」を選択します。











「1_名無し」という新しいフォルダが作成され、テキストボックスに入力可能な状態でフォーカスして表示します。
右クリック選択後、右手をキーボードに戻してそのままフォルダ名を入れられます。エンターキーで確定です。

「1_名無し」という初期フォルダ名が2ch的で仕事で使いづらいという注文は、作者の趣味の問題なので答えられません。






純正リアバッグとバウハウス・デッサウ展

先週上野に来た時にバウハウス展のポスターを見かけこれは行かねばと思っていた。というのも、15年前の頭でっかちな受験生のとき、試験で東京に来てJRのホームでバウハウス展のポスターを見て、駅のホームでそんな宣伝をする東京ってすげえなと思いつつ、大学が京都になって行けずじまいになっていた心のしこりを消化せねばという気持ちもあったため。おかげで当時の生パイプチェアが見れて、何だか実らなかった片思いにケリがついたか。今はニーチェアが欲しい。涼しくなったらニーチェアをBSMのリアキャリアに積んで公園に行きたいと思うが、70cm超で6kgというのは荷が重い。

BSMのオプションの布製リアバッグをつけてみた。カタログ写真からうかがえるおやじ臭漂うデザインではなかなか踏み切れないものがあった。しかも、写真のような深緑がよかったが、届いたのは黒。でも、それ以外はいい点ばかりだ。つくりはしっかりしているし、サイドポケットがすごく便利で、走りながらでも手を伸ばして出し入れができる。荷物もどっさり入り、出先の買い物でコンビニ袋をサドルにぶら下げてシャカシャカすることもないし、荷物の重心もサドルバッグより低い位置になって安定感もよし。今さらながらモールトン(変態小径)博士の理念に関心している次第。


mirrorMan - フォルダ参照

無題
いわゆる特殊フォルダを扱うのに難があったため、無効になっていた browsfol.pngボタンを動作するようにしました。押すとフォルダ参照画面が表示されます。




folview.png






コンピュータを選ぶと、
comv.jpg

アドレスバーに「コンピュータ」が表示され、アイテムを表示します。

Windowsにはいろんなタイプのフォルダがあり、そのすべてがNameSpace()で同じように更新日時のプロパティや、対象ファイルのオブジェクトを取得したりできるわけではありません。
「コンピュータ」なら、レジストリで「コンピュータ」という名前にひもづく物理的なCLSIDがあり、内部から扱うにはこちらからオブジェクトを取得しなければなりません。


そのため、Scripting.Dictionaryに「コンピュータ」というKeyと「::{20D04FE0-3AEA-1069-A2D8-08002B30309D} 」というItemの組みあわせを記憶させておき、必要に応じて「コンピュータ」KeyにひもづけてCLSIDを取得します。そして、Dictionaryの情報のうち次回起動時にあらかじめ取得しておくべきものをINIファイルに書き込んでおきます。

var ss ="",sp ="",spcs =[];
var arK = (new VBArray(dicSpecil.Keys())).toArray();
var arI = (new VBArray(dicSpecil.Items())).toArray();
$("span.setLstSpn").each(function(i){
ss +="[setLst]\t"+ this.id +"\t"+
dicIniLft.Item(this.id) +"\t"+ dicIniRht.Item(this.id) +"\r\n";
for(var i in arK){
if((arI[i] == dicIniLft.Item(this.id))||(arI[i] == dicIniRht.Item(this.id))){
spcs.push(arK[i]);
for(var j in spcs) if(arK[i] == spcs[j]) var k = 1;
if(k) sp +="[spcLst]\t"+ arK[i] +"\t"+ arI[i] +"\r\n";
}
}
});

JScriptにはINI書き込みの標準関数の類はないので、自分でやります。dicSpecilオブジェクトがDictionaryです。jQueryの$()で指定しているclass属性setLstSpnは画面左上のmzip、最新版等のユーザ登録のボタンリストのものです。これをeach()メソッドで回しています。後の細かい動作の説明はここでは省略します。



ペダル - PD-M540装着

以前錆び錆びMTBのペダルで断念したことがあり、今回はHOZANのペダルレンチを注文した。さすがに手では外れないので、サイクルベースあさひのメンテナンスページを参考に。
逆の足でペダルにのり、リアにブレーキをかけつつ、もう一方の手でレンチを支える曲芸のような状態で息を止めて瞬間的な蹴りの一撃をくらわす。ゆるんだ途端に猛烈なグリスの腐臭をくらった。
臭いグリスをきれいにふき取り、ペダルとサドルのネジ山にズラ油をまんべんなく塗布。ズラ油はガキんちょ心をくすぐるスライムのような色がなんともいえない。ヌルヌルと金属にまとわりつく様子はなんだかエロすら感じてしまう。





はりきって明治通りを渋谷方面へ。新宿で車道も人もいっぱいになり、これはビンディグ付けたてにはつらいな、山手通りを迂回しようかなあと、5丁目あたりの大きい信号待ちで足をつかずに悩んでいたら、ペダルが外れない!やりましたBSMで初ゴケ立ちゴケ。うわーと左手を地面につき、ひざも出してチャリを守りました。とはいってもガシャーと音を立て、両足ともペダルに固定されて自転車にまたがった姿勢のままアスファルトに横たわる姿は、普通の人には変テコに見えるんだろうなと、そんなことがよぎらせながら数秒間動けません。ひざからも少し流血。

なぜ足が外れなかったのか、画像下の強さを設定するボルトは最弱にしているはず・・・
そう、このボルトは裏面にもあり、片面しか調整していなかった!と気づいてもあとのまつり。
はめる時にもたしかに固いときがあったのだが、クリートを入れる感覚に慣れてないので角度でも悪いのかなと思っていた。はあ。ご多聞にもれずやってしまうものだ。












mirrorMan - 正規表現フィルタ

大量のファイルからキーワードで検索するとき、思わず正規表現でしたくなることがあります。思わずしたくなるといっても性器表現ではありません。Regular、「正規」。この日本語訳もどうかと思います。今はやりの雇用問題でいうと「非正規」社員は存在が「イレギュラー」なメンバーかということになってしまいます。正規表現はそういう意味での正規な表現ではなくて、
そんなことはさておき、エクスプローラのワイルドカード検索のかわりに正規表現でフィルタします。

右クリックメニュー内のテキストボックスにキーワードを入力し、エンターキーで実行します。右の画像の場合、mirで始まり.htaで終わるファイルを抽出しています。キャンセルはESCキーです。




ソースはこんな感じです。
function jqContextMenuDsp(){ //contextmenu.r2.js:singleton menu id
if(! document.all.jqContextMenu) return false;
return (jqContextMenu.style.display =="block");
}
右クリックメニューに使用しているcontextmenu.r2.jsはsingletonなノードIDがあるので、これを利用しています。
IEの場合、存在しないノード(タグのid属性)を参照すると、変数が定義されていないとエラーを返すので、document.allからノードツリーをたどって確認します。存在すれば、displayプロパティがblockかどうかを返します。
if(jqContextMenuDsp()){
try{ var re = filterLstBox[2].value?new RegExp(filterLstBox[2].value,'i'):/./}
catch(e){wsh.popup(e.description, 1,document.title,64); return}
}
テキストボックスに値が入力されていれば、オブジェクト変数reにRegExpでnewしておきます。
try{}catch{}しているのは、ユーザが入力した正規表現のコンパイルエラーを逃がすためです。
正規表現式でなかった場合、このようなポップアップで知らせます。

regpop.png

あとは、フォルダのコレクションで回してhtmlを生成する部分で次のようにひっかけています。
var itm, ssh = new ActiveXObject("Shell.Application");
var erfo = ssh.NameSpace(er);
for(var fc=new Enumerator(erfo.Items()); !fc.atEnd(); fc.moveNext()){
itm = fc.item();
if(re) if(!re.test(itm)) continue;

}



ちょっと自転車で日本一周してくる、の人


ニコニコ動画で自転車動画をみていたら、
再生回数1位に自転車ものが。
いたって普通の人(本人談)が離職してGIANT OCR1で日本一周の動画。
あれよあれよと、
まとめwikiが立って、
mixiにもコミュができ、
2chのスレもpart2。
何より動画のクオリティが高い。

スゴす!




adidas Cyclone@上野公園


adidasのシューズを買いにY's上野へ。ここは店員さんの姿勢もよくていい雰囲気。
El Moro > Minnret > Cyclone の欲しいもの順に足を入れてみる。展示品もうまくサイズをばらして陳列してあって、気配りを感じる。
El Moroは少し重い。靴ひもをマジックテープで止めるのはチェーンにひっかかる心配がなくていいのだが、履いた感じもゴツいイメージ。
Minnretは感触はいい。が、靴紐を通す穴がすべりやすく、きっちり縛るのに難があって致命的。
Cycloneは意外にもフィット感が一番で、軽さも好印象、細い紐でもきっちり縛れた。
こうなると問題は色。飾りのないシルエット勝負のデザインなので、黒は少し遠目にみるとヤボったい感じにしか見えない。しかし白は汚れが・・・沈黙で迷うこと5秒後、白に。念のため左にも足を入れて確認してくださいと、店員さんは非常に丁寧。

帰りに上野公園へ寄って、西郷隆盛像を拝む。30分ほど前のベンチで休憩していたが、途切れることなく人が訪れるのは、最後まで男を上げ続けた生き様に今でも慕う人が多いからか。今までみた公園の銅像では別格のようだ。薄暗い洞窟で自刀して果てようと、これまでもこれからも西郷隆盛の生きざまで心が熱くなる人は絶えないだろうと思う。薩摩のオラが主義的な文化は自分にはよくわからないし、大久保の故郷薩摩より国家を優先する姿勢もそればかりが正義だとは思はないが、不本意であれ、敗北と死が待っていることが分かっていてであれ、男を曲げずに通していく様は、物事はどうあるべきかという時にいつも思い出される。

自刀した西郷洞窟。もの悲しい。
シューズは買った帰りに一緒に撮っただけで意味はありません。西郷さん一緒に撮ってすみません。












while(aho.atEndofStream)

笹部 政宏
笹部 政宏
mail




フリーソフツ
Category
はてブ
Monthly Archive
New Entry
New Comment
New Trackback
RSS
Copyright © Kittens flewby me All Rights Reserved.