Home > JavaScript

JavaScript Archive

デバッグ用 jQuery プラグイン

たくさん console.log 書くのが面倒なのでこんな風にしてます。

(function($){$.extend($.prototype,{
op: function(s){
    s = $.extend({o: console.log, n: toString}, s);
    $(this).each(function(){
        s.o('{width: '+$(this).width()+', height: '+$(this).height()+', scrollLeft: '+$(window).scrollLeft()+', scrollTop: '+$(this).scrollTop()+'} as '+s.n.call($(this)[0]));
    });
}})})(jQuery);

プラグインと言うほどの物ではありませんね。
$(selector).op(); で console.log に {width: nnn, height: nnn, scrollLeft: nnn, scrollTop: nnn} as [object name] が表示されるだけ。
jquery ui の resize() メソッドにつなげて確認、みたいな。
$(selector).op({o:$(’#log’).html}); とかでもいけるけど追記するような処理加えないと複数要素が駄目。

Wordpress におけるメタボックスの構造解説

Wordpress 2.5 辺りから整備されてきたメタボックス。2.7 にもなるとかなりシステマチックな構造となってきました。
このメタボックスの構造があるおかげで 2.7 からはユーザーごとに「表示オプション」という形でそれぞれのページでのメタボックスをコントロールできています。

さて、このメタボックス。プラグインでも存分にその機能を利用できます。設定項目が多岐に渡るようなプラグインの場合、設定画面の UI が煩雑になりがちです。
そんなときにこのメタボックスを利用する事で、すっきりとシステマチックな UI を設定画面に提供する事が出来ます。

使い方はいたって簡単。

  1. メタボックスの登録
  2. メタボックスの出力
  3. メタボックス状態の保存と復元

これだけです。

メタボックスの登録

<?php
add_meta_box( 'メタボックスの識別名', 'メタボックスのラベル', 'コールバック関数', 'ページ名', 'コンテキスト', '優先度');
?>

これがメタボックスを登録する関数です。
まず、第一引数にメタボックスの識別名を指定します。これは最終的にメタボックスを HTML として出力する際、一番外側の div 要素の id 属性として利用されますので、制限的には id 属性のそれに準じます。PHP 側ではハッシュのキーとして使われます。
同一のページ内で使うメタボックス同士で重複してはいけませんし、そもそも id 属性として利用されるので HTML 内で重複してもいけません。ユニーク性を強調するならば ‘プラグイン名_メタボックス識別名’ という様な構造がお手軽です。

次に第二引数。これはそのままメタボックスの上部に表示されるラベルです。それ以外に利用される事はありません。
また、この引数はそのまま HTML に出力されるので、タグを利用してメタボックスの表現に変化をもたせることが可能です。しかし、ラベルは span 要素で括られているためボックス要素を利用する事は出来ません。せいぜい <span class=”extra”>ラベル</span> とする程度にとどめた方がよいでしょう。

第三引数はコールバック関数です。後述する do_meta_boxes() でメタボックスの HTML が出力される際に呼び出されます。
つまりメタボックス内部の HTML を出力するための関数やメソッドを指定します。
例えば、コールバック関数に display_meta_box() を指定した場合 display_meta_box() では以下のようなコードを書きます。

<?php
function display_meta_box(){
?>
<label>今朝食べたもの<input type="text" name="breakfast" value="スパンコール丼" /></label>
<?php
}

call_user_func() で呼び出されますので、メソッドの場合は配列で指定します。

第四引数は ‘ページ名’ となっていますが、これはプラグインの URI には依存していません。自由です。
ページ名というよりはページの識別名と考えた方がよいかもしれません。後述する JavaScript 側でのコントロールにおいて重要な役割を持ちます。
プラグイン名を利用するのがベターでしょう。

第五引数のコンテキストは、要するに同一ページ内に複数列のレイアウトを組むような場合の識別名として利用します。
例えば以下のような HTML があったとします。

<div class="sidebar"></div>
<div class="body"></div>

sidebar と body にはそれぞれ別のメタボックスを出力したい、という様な場合にこのコンテキストで分類し、後述する do_meta_boxes() で区別して呼び出します。
指定しない場合は ‘advanced’ として扱われます。

最後の第六引数は優先度です。優先度は高い順に ‘high’, ’sorted’, ‘core’, ‘default’, ‘low’ となっており、これ以外の優先度を指定してしまうとメタボックスが出力されなくなってしまいますので気をつけてください。優先度が適用されるのは「メタボックスが呼び出される順番」です。プラグインの構造上出力したい順番にメタボックスの登録が出来ない場合などに力を発揮します。
指定しない場合は ‘default’ として扱われ、優先度が重複するメタボックス同士は登録された順に出力されていきます。

以上がメタボックスの登録関数について。

メタボックスの出力

次に登録したメタボックスを出力する関数である do_meta_boxes() についてです。

<?php
do_meta_boxes( 'ページ名', 'コンテキスト', 'コールバック関数に渡したい変数');
?>

第一引数と第二引数はそれぞれ add_meta_box() で指定したものと相関関係にあります。
呼び出した居場所で適時呼び出して下さい。

<div class="sidebar"><?php do_meta_boxes( 'pluginName', 'sidebar' )?></div>
<div class="body"><?php do_meta_boxes( 'pluginName', 'body' )?></div>

という様な具合です。
第三引数にはコールバック関数に渡したい変数を指定することが出来ます。
コールバック関数には二つの引数が渡されます。

function callbackFn( ‘do_meta_boxesから渡された変数’, ‘このコールバック関数を呼び出しているメタボックスの設定’ ) となっておりますので、例えば1種類のコールバック関数で複数のメタボックスを出力したい場合などには、第二引数で呼び出し元のメタボックスを評価し第一引数にある変数を使ってメタボックスを構成する、という様な利用方法が挙げられます。

メタボックス状態の保存と復元

ここまでは PHP のお話でしたが、このメタボックスは JavaScript によって折りたためたり、ドラッグして移動する事ができます。
これらの直感的な操作は wp-admin/js/postbox.js にそのスクリプトが書かれていますので、とりあえずこれを呼び出します。
postbox.js は規定のスクリプトとして登録されているので、呼び出しは wp_enqueue_script( ‘postbox’ ); で OK です。

呼び出そうと思っている本体のスクリプトの呼び出し名を知りたい場合は以下の URI を参照して下さい。
Function Reference/wp enqueue script « WordPress Codex

次におまじないを2行、JavaScript として追加します。

postboxes.add_postbox_toggles('ページ名');
jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');

1行目はメタボックスのイベント登録をします。
また、メタボックスの状態を保存する際にどのページで出力されたメタボックスの情報であるかを識別するページ名を引数に渡します。
このページ名は前述の add_meta_box() で指定したページ名と同一のものを利用します。
これによって PHP 側で生成したメタボックスと、JavaScript 側で制御している表現の状態を結び付けます。
2行目はメタボックスが閉じられたものであると指定された場合に、そのメタボックスを予め閉じるための指示です。
PHP で生成されたメタボックスが閉じられる予定のものであった場合、class 属性に if-js-closed が指定されていますので、そのクラス名を closed に変えています。
これにより closed のスタイルが適用される事になります。

JavaScript によってメタボックスを閉じたり、移動した情報はその度にサーバにリクエストされます。
その際 nonce_field が無いと状態を保存してくれません。
ページ内のどこでもよいので nonce_field を出力しておきましょう。

<?php
wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false );
wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false );
?>

これで OK です。
nonce_field の説明は長くなってしまうので機会があれば別エントリで言及しますが、これは簡単に言えばユーザーの権限評価も含めたワンタイムチケットです。

メタボックスが表示され、状態が保存されていれば全てはうまくいったという事です。
さほど複雑な構造ではないので是非利用してみて下さい。

参考

ext.jsのグリッドを1行しか選択できないようにする

ふあー、会社設立してからものすごく忙しくてこのブログのデザインを変えることはおろか会社のウェブサイトの制作にすら手が回ってない、言い訳からどうもこんにちは。ご無沙汰しています。

コネタ。

var grid = new Ext.grid.GridPanel({hogehoge});
grid.on('cellmousedown', function(){
var selected = this.selModel.getSelected();
this.selModel.clearSelections();
this.selModel.selectRecords([selected]);
});

もっとスマートな方法あるのかな。
これで shift やら ctrl 押しながら複数選択したときに選択しないようになります。

photoshop で新規作成時の名前を自動的につける

先日 MercuriusLab のきりゅさんが「photoshop で新規作成するときに”日付_時間_秒”が自動的に名前になってたらなあ」と IRC でつぶやかれていたので脊髄反射で作りました。

var d = new Date();
var defaultName = d.getFullYear() + '' + ( d.getMonth() + 1 ) + '' + d.getDate() + '_' + d.getHours() + '' + ( '0'.substr( 0, d.getMinutes().length ) ) + d.getMinutes() + '_' + d.getSeconds();
documents.add( 800, 600, 16, defaultName );

という感じ。
メモ帳にコピーペーストして [適当な名前.jsx] などと名前をつけて保存して、photoshop のファイル>スクリプト>参照で保存したスクリプトを実行するとドキュメントを新規作成します。

documents.add( 800, 600, 16, defaultName ); は新規作成メソッドで、それぞれ 800 が幅(px)、600 が高さ(px)、16 がカラーモード、defaultName が新規作成時の名前になります。

もっと色々と指定できるので、詳しくは web で。
http://www.adobe.com/devnet/photoshop/pdfs/JavaScriptReferenceGuide.pdf

メールアドレスの収集に立ち向かう

メールアドレス収集ボットにメールアドレスをぶっこ抜かれないよう画像などで表示することがありますが、たまにこの画像をアンカータグでマーカップしてるページを見かけます。
これってあんま意味ないですよね。アンカータグの href 属性をチェックされたら一発でアウトです。
と言うわけで、JavaScript と UTF-8 の制御文字を使って「見た目と中身がちょっと違うメールアドレスのリンク」を作ってみました。

制御文字

Unicode には制御文字という種類の文字が存在します。細かい説明は割愛しますが、文字自体を制御する機能を持った小さな制御コードというような概念です。
で、WindowsXP だとエクスプローラなんかでファイル名入力するとき、コンテキストメニューに「UNICODE 制御文字の挿入」というのがあると思います。でさらにこの UNICODE 制御文字に「LRO」ってのと「RLO」ってのがあると思います。

UAX #9: The Bidirectional Algorithm によると

The following codes allow the bidirectional character types to be overridden when required for special cases, such as for part numbers. These codes allow for nested directional overrides.

RLO Right-to-Left Override Force following characters to be treated as strong right-to-left characters.
LRO Left-to-Right Override Force following characters to be treated as strong left-to-right characters.

The precise meaning of these codes will be made clear in the discussion of the algorithm. The right-to-left override, for example, can be used to force a part number made of mixed English, digits and Hebrew letters to be written from right to left.

とあります。要は「この制御文字以降の文字の表示方向を変える」という意味合いのものです。
実用とはかけ離れた使い方ですが、ダメっつうことはないと思います。

メールアドレスだけ右から左に表記

例えば

スパンコール丼

‮丼ルーコンパス‭

この二つは見た目は同じだけど下の方は実際には「丼ルーコンパス」と入力されています。
この「丼ルーコンパス」の直前に RLO を、直後に LRO を挿入することで「丼ルーコンパス」部分だけが「右から左に表示」と言うことになります。

どうやって入力するの?

Microsoft IME パッド - 文字一覧実体が入力できれば問題ないのですが、キーボードで入力できるわけではありません。
直接入力したい場合、WindowsXP で Microsoft IME を利用しているならば、IME パッドの文字一覧から選択することが可能です。
デフォルトではおそらく Shft_JIS となっているかと思いますので、まず Unicode を選択します。
LRO のコードは \u202D で、RLO は \u202E ですので、大体”一般句読点”のグループ辺りに存在します。
表記される文字なり記号なりがあるわけではないので、空白となっていますので、マウスオーバーで表示されるコードを参考に選択してみて下さい。

そんな面倒なことアレだ!と言う向きもおられるかと思います。そういう方は数値実体参照で入力なさってもよろしいかと。
LRO のコードは \u202D ですので、10進数で表した数値実体参照は &#8237; となります。
同様に RLO ならば \u202E ですので、数値実体参照は &#8238; となります。

文字コードの表や実体参照に関しては

辺りを参考にして下さい。

アンカータグっぽく

さて、表記を逆方向に変えたとしてもそれがアンカータグの場合正常なメールアドレスだと判断してくれはしません。当たり前ですね。
さらに普通にアンカータグを書くのも意味が無いので却下。と言うことで閲覧者の環境に左右してしまいますが JavaScript を使ってアンカータグの様な働きを作ります。

ソースはこんな感じに。

document.getElementById("mailto").onmouseover = function(){
    document.getElementById("mailto").style.cursor = "pointer";
    document.getElementById("mailto").style.color  = "#e4007f";
};
document.getElementById("mailto").onmouseout = function(){
    document.getElementById("mailto").style.cursor = "normal";
    document.getElementById("mailto").style.color  = "#444444";
}
document.getElementById("mailto").onclick = function(){
    var result = "mailto:";
    var i = 0;
    var m = ["77", "6f", "72", "6b", "73", "40", "53", "50", "61", "69", "53", "2e", "6a", "70"];
    while(true){
        if(i > m.length - 1) break;
        result = result + "%" + m[i];
        i ++;
    }
    location.href = result;
}

CSS 的な表現部分は割愛するとして、メールアドレスを生成するのに逆向きのメールアドレスを span タグなどでマーカップし、id 属性を mailto としています。
そして、URL エンコードで表現したメールアドレスをさらに % を取り除いて配列に格納しています。
これを while で1文字ずつ連結して location.href に渡すことでアンカータグと同様の働きをさせています。

※アルファベットと半角で表現できる記号は Unicode でも Ascii 互換ですので、URL エンコードしたとしてもコード自体は Ascii と同じです。

効果はあるのか

結局こういうのはいたちごっこなわけで、この方法に対応した解析を行われてしまえば意味はありません。
しかし少なくとも単純にメールアドレスの形式を持った文字列を収集するだけのボットであれば、上記で生成したメールアドレスがメールアドレスだと認識できることはないので、多少なりとも効果があるのではないでしょうか。
上記のソースは方法論として例に挙げただけなので、実際に使う際には独自のスクランブル(逆から連結とか、順番に応じてコードを計算するとか)を織り交ぜてさらに難読化することで、ボットの収集を防げるのではないかと思います。

デメリット

当然ながら Javascript が有効でないと全く動作しません。ページの文字コードも Unicode である必要があります。
連絡手段として 100% 開放できるわけではないので、確実性が要求されるシーンで利用されることはお勧めしませんが、個人的なものであればこの程度は問題ないかと思います。

そんな回りくどい事しなくても、こんな方法があるぜ!と言う情報がありましたらコメントでも ○○@△△(誰かに突っ込まれる前に見事に収集されたので削除:2007/11/16) までメールでもお寄せいただければ助かりマスク。

ホーム > JavaScript

Search
Feeds
Meta

Return to page top