Personal tools
You are here: Home ブログ hamabe Categories JavaScript
« December 2010 »
Su Mo Tu We Th Fr Sa
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Recent comments
Re:コマンド入力を実装しよう inoue 2007-08-14
 
Document Actions

JavaScript

Up one level

Document Actions

コマンド入力を実装しよう

[NS] お知らせ:「コナミコマンド」を実装しました. に感動してしまった。

さっそく自分でもJavaScriptでの実装を試みたところ、以外と使えそうなので公開。

これは何?

  • 任意の文字列(コマンド)を入力した後に実行する関数を簡単に設定するものです
  • サンプル.をご覧ください、解説も一緒です(2007/08/12 00:50追記: IEでエラーが起きていたので修正。自爆コマンドでちゃんと致命的エラーが起きるようJavaScriptエラーを修正しました)

使用例

本体:

var KONAMI = function() {
var command_list = [];
var disabled = false;
var permit_key = ' 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var func_key = {
8: 'back', 9: 'tab', 13: 'enter', 16: 'shift', 17: 'ctrl', 18: 'alt',
27: 'esc', 33: 'pageup', 34: 'pagedown', 35: 'end', 36: 'home',
37: 'left', 38: 'up', 39: 'right', 40: 'down', 46: 'delete'
};

var make_key = function(key) {
if (!key) return ['up','up','down','down','left','right','left','right','b','a'];
if (typeof(key) == 'string') key = key.split(',');
var temp = [];
for (var i = 0, len = key.length; i < len; i++) temp = temp.concat(parse(key[i]));
return temp;
};

var parse = function(key) {
for (var i in func_key) if (key == func_key[i]) return [key];
var arr_char = key.split('');
for (var i = 0, len = arr_char.length; i < len; i++) {
if (permit_key.indexOf(arr_char[i]) == -1) arr_char[i] = '*';
}
return arr_char;
};

var kc2char = function(kc) {
if (kc >= 48 && kc <= 57) return String.fromCharCode(kc);
if (kc >= 96 && kc <= 105) return String.fromCharCode(kc-48);
if (kc >= 65 && kc <= 90) return String.fromCharCode(kc+32);
if (!!func_key[kc]) return func_key[kc];
return (kc == 32) ? ' ' : '*';
};

var check_key = function(evt) {
if (disabled) return;
if(/input|textarea/i.test((evt.target||evt.srcElement).tagName)) return;

var c = kc2char(evt.keyCode);
if (c.length == 1 && evt.shiftKey) c = c.toUpperCase();

for (var i = 0, len = command_list.length; i < len; i++) {
var command = command_list[i];
if (!command.cache) command.cache = [].concat(command.key);

if (command.cache[0] == '*' || command.cache[0] == c) {
command.cache.shift();
if (command.cache.length == 0) {
command.action();
command.cache = [].concat(command.key);
}
} else if (c == 'shift' || c == 'ctrl' || c == 'alt') {
continue;
} else {
command.cache = [].concat(command.key);
if (command.cache[0] == c) command.cache.shift();
}
}
};

if (document.addEventListener) { document.addEventListener('keyup', check_key, true); }
else if (document.attachEvent) {
document.attachEvent('onkeyup', check_key);
var unload = function(){ document.detachEvent('onkeyup', check_key); window.detachEvent('onunload', this); };
window.attachEvent('onunload', unload);
}


return {
command: function(action, key) { command_list.push({ action:action, key:make_key(key) }); },
disabled: function() { disabled = true; },
enabled: function() { disabled = false; }
};
}();

以下のように隠しコマンドを設定します

  • KONAMI.command(アクション, コマンド);

使用例:

KONAMI.command(function(){ window.open('mailto:hoge@fuga') }, 'mail to hoge');
KONAMI.command(bookmarklet_1, 'book,enter,1');

その他ポイント

  • いくつコマンドを登録してもイベント登録はひとつだけ
  • keydownでなくkeyupにイベント登録している。keydownだとキーダウン中に別のキーのkeydownイベントが拾えない。『キーアップ中』なんてものはないのでkeyupイベントはかぶらない。今回のような長文のコマンド入力を間違いなく拾うにはkeyupの方がよい(ただしCtrlやAltとの合わせ押し判定の精度は落ちる)
  • 最近流行のアニメーションだとかスケスケだとか。嫌いな人のために、そういったリッチ化はコナミコマンドで行おう
  • 自爆コマンドをもっと広めたい
Category(s)
JavaScript
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/hamabe/30b330de30f35165529b30925b9f88c5305730883046/tbping

Re:コマンド入力を実装しよう

Posted by inoue at 2007-08-14 11:39
次のマルスケでは、パワーアップコマンドを発行するとProjectAになるとか。

逃げるゲーム with jQuery

jQueryを少し触ってみた。いろいろと試しながら遊んでいたらなんだかゲームっぽいのができた。


逃げるゲーム.

マウスで逃げて下さい。

使用されている画像は、弊社製品AirOneにおける『ミーティング』を示す画像と、『出欠の返事がまだですよ!』を示す画像です。

自分的にはこの画像に追われるのは慣れっこですが、精神的にくるものがあります。

AirOneでもこんな感じに、画像が追ってきて捕まったら出欠返信フォームが自動的に開いてしまうような機能をつけるといいのかも。


ソース.

なにかの参考になるかもしれません。


簡単な解説

jQueryはある要素にアニメーションをどんどん追加しても、自動的に順番待ちしてくれる。

順番待ちのfunctionはElement.queue.fxの中に入れられるようだ:

var daaaaaah = function(){ $('#hoge').animate({ left:0 }) };
$('#hoge').animate({ left:100 }, daaaaaah); // -> 1
$('#hoge').animate({ left:200 }); // -> 2
$('#hoge').animate({ left:300 }); // -> 3

上記が実行される順番は『1、2、3、daaaaaah』である(daaaaaahは1のコールバック)。

1のアニメーション中、2と3は$('#hoge')のキューに入り順番待ち。

1が終わるとdaaaaaahがキューに登録され、2が実行される。


このゲームはこのキュー待ちを利用している。全ての敵は自分のマウスの軌跡を追ってくるが、

キュー登録の間隔がアニメーションの間隔よりも短い敵はワンテンポ遅れて追ってくる

また、速く逃げるほど速く追ってくるので、マウスの移動量(=onmousemoveの回数)をScoreにしてみました。

Levelは敵の数です。


その他のポイント

  • animateでleftやtopをアニメーションさせたいとき、初期値を指定しておかないとIE7でエラー?
  • ゲームオーバーの判定は、全ての敵にonmouseoverイベントを設定してしたいとこだが、
    document.onmouseoutを一つ設定することで済ます(子要素のmouseoverで親要素のmouseoutも発生する)
    • ただIE7でマウスを全く動かさなかった場合、子要素が勝手にマウスの下に潜り込んでもイベントは発生しなかった(裏技)
  • 『マウスの移動量 = onmousemoveの回数』って計算はよくないっぽい。速く移動すればmousemoveイベントはすっ飛ばされる。
  • 初めてのjQuery、どういう書き方をしたら読みやすいかわからなかった。インデントは多めが吉。


The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/hamabe/9003308b30fc30e0-with-jquery/tbping

LDRize + iframe


LDRizeを自分用にカスタマイズしたものが意外と評判よかったので公開します。


主な特徴

  • 『i』キーを押すと、iframeでその場にページを開きます

  • iframe内のページはSpace, Shift-Spaceキーでスクロールできます
  • 1番目の項目は自動で開いてFeeling Lucky♪ (Googleのみ有効)


[ScreenShot]

LDRize+iframe



メモ書き

  • iframe内に開いた異なるドメインのサイトは、セキュリティ上JavaScriptによる操作はできない
  • 今回はスクロールしたいだけだったので、以下のような感じでおk
addEventListener(document, 'keydown', function(e){
if(e.keyCode == 32){
$('_iframe').contentWindow.focus();
setTimeout(function(){ window.focus() }, 0);
}
}, false);
  • ただし上のはカレント項目がiframeで開かれているときのみ発動させる
  • I'm Feeling Luckyがウザい人はLDRize.initの最後の一行を削除でおk
  • 以下のパッチを各自よくみて、自己責任でお願いします


:ldrize.patch

*** 11562.user.js	2007-10-31 01:20:50.000000000 +0900
--- ldrize.user.js 2007-10-31 01:23:38.000000000 +0900
***************
*** 16,21 ****
--- 16,22 ----
'S-j' : 'NextPage',
'S-k' : 'PrevPage',
'v' : 'View',
+ 'i' : 'Iframe',
'p' : 'Pin',
'o' : 'Open',
'l' : 'List',
***************
*** 31,36 ****
--- 32,38 ----
'NextPage' : 'Scroll next page',
'PrevPage' : 'Scroll prev page',
'View' : 'Open in current tab',
+ 'Iframe' : 'Open in iframe',
'Pin' : 'Pin',
'Open' : 'Open pinned items or current item',
'List' : 'Toggle pinned items list',
***************
*** 199,204 ****
--- 201,207 ----
}

LDRize._enable = true;
+ document.addEventListener('keydown', LDRize.focusOnIframe, false);
document.addEventListener('keypress', LDRize.handleKey, false);
document.addEventListener('mousemove', function(){LDRize.invisibleRemove(LDRize.invisiblelist)}, true);
LDRize.initCommand();
***************
*** 216,221 ****
--- 219,225 ----
css += LDRize.setCSS();
css += LDRize.initSpace();
if(css != '') addStyle(css);
+ if(window.document.URL.match(/http:\/\/.*google.*\/.*/)) LDRize.viewCurrent('iframe');
}
},
initBindCommand : function(){
***************
*** 224,229 ****
--- 228,235 ----
LDRize.bindNextPage = LDRize.scrollNextPage;
LDRize.bindPrevPage = LDRize.scrollPrevPage;
LDRize.bindView = function(){LDRize.viewCurrent('here')};
+ LDRize.bindIframe = function(){LDRize.viewCurrent('iframe')};
+ LDRize.bindIframeFocus = LDRize.iframeFocus;
LDRize.bindPin = LDRize.attachPin;
LDRize.bindOpen = LDRize.openPinned;
LDRize.bindList = LDRize.togglePinList;
***************
*** 758,763 ****
--- 764,771 ----
if(LDRize.css_highlight_link) css += "\n.gm_ldrize_link {" + LDRize.css_highlight_link + "}";
if(LDRize.css_highlight_pinned) css += "\n.gm_ldrize_pinned {" + LDRize.css_highlight_pinned + "}";
css += ".gm_ldrize_invisible { visibility:hidden; }";
+ css += ".gm_ldrize_iframe { border:3px ridge #6f6 !important; }";
+ css += ".gm_ldrize_iframe iframe { width:100% !important; min-height:200px !important; border:none !important; }";
return css;
},

***************
*** 1091,1101 ****
--- 1099,1133 ----
LDRize.scrollNext();
}else if(type=='here'){
window.location.href = url;
+ }else if(type=='iframe'){
+ if(!LDRize.current_parapraph) return;
+ var node = LDRize.current_parapraph.lastChild;
+ if(!node || (node.nodeType == 1 && node.className.match(/gm_ldrize_iframe/))) return;
+ if(url.match(/.pdf$/)){ LDRize.viewCurrent('here'); return; }
+ var div = document.createElement('div');
+ div.setAttribute('class', 'gm_ldrize_iframe');
+ var iframe = document.createElement('iframe');
+ iframe.style.height = (window.innerHeight - LDRize.current_parapraph.offsetHeight - 25) + ' !important;';
+ iframe.src = url;
+ iframe.addEventListener('load', function(){ window.focus() }, false);
+ div.appendChild(iframe);
+ LDRize.current_parapraph.appendChild(div);
}else{
window.open(url);
}
},

+ // space
+ focusOnIframe : function(event) {
+ if(event.keyCode != 32) return;
+ if(/input|textarea/i.test(event.target.tagName)) return;
+ if(!LDRize.current_parapraph) return;
+ var node = LDRize.current_parapraph.lastChild;
+ if(!node || node.nodeType != 1 || !node.className.match(/gm_ldrize_iframe/)) return;
+ node.firstChild.contentWindow.focus();
+ setTimeout(function(){ window.focus() }, 0);
+ },
+
// ?
toggleHelpMessage : function(){
return (LDRize.hideHelpMessage() || LDRize.showHelpMessage());

ldrize.patch ldrize.patch
Size 3.8 kB - File type text/x-patch
ldrize.user.js ldrize.user.js
Size 55.0 kB - File type application/x-javascript
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/hamabe/ldrize-iframe/tbping

ShareOnTumblrで投稿できない件

Tumblrがv3になった(?)ため、JSAction版のShareOnTumblrでエラーがでます。

投稿しようとするとPost failed.と怒られて投稿できなくなってしまいました。

ぐぐっても見当たらないのでソース見てみたらpostするURLが変わっているだけっぽかったので、そこ書き換えてみたら動いた。

『params.v = '3';』はなくても動きましたが一応つけておきます。


ShareOnTumblr.js:. 722行目付近

//	postByXHR('http://www.tumblr.com/publisher/save', params, onload, onerror);
params.v = '3';
postByXHR('http://www.tumblr.com/share', params, onload, onerror);

配布元が修正されるまで、とりあえず。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/hamabe/shareontumblr62957a3f304d306a30444ef6/tbping

GoogleReaderでスペースキーをLDR風に使うGreasemonkeyスクリプト


最近GoogleReaderを試しているのですが、
ざっと使って見たところ大きな不満点は『スペースキーのスクロールをLDR風にしたい』ってぐらいで、
後は思っていた以上に使いやすくていい感じです。
『*1, *2, *3, ...』のようなタグを作っておけばLDRのレートちっくな機能も簡単に実現できます。


ということで書いた修正スクリプトが割といい感じだったので公開しておきます。


単純にkeydownイベントを追加するだけでは他の機能とバッティングしてしまうし、
かといってイベント伝搬を止めてしまうのは問題外なので、
今回は頑張って難読化されたJavaScriptコードを追いかけて改変してみました。

Googleの難読化されたJavaScriptと戦うための戦略

# 最近上記アカウントでひっそりとブログを始めましたが、よい成果物ができたときにはありえるえりあでも公開します。


grspacekey.user.js grspacekey.user.js
Size 1 kB - File type application/x-javascript
The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/hamabe/googlereader30b930fc30b930ad30fc3092ldr98a8306b4f7f3046user.js/tbping

Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.