GANCHIKU.com

Prototype Window Classをもう少し使ってみるテスト

Services_YouTubeのサンプルを作る際に使用したPrototype Window Classをもう少し使ってみた。以前、こういうの作りたかったんだよなーなんてのが結構簡単にできそう。アラートなんかも結構快適かも。

Prototype Window Class

ただやっぱりWindowの中にYouTubeのswfファイルを使用させるのはかなり重くなりそう。

で、こんな感じか。

Open Window

  • default
  • mac_os_x
  • spread
  • nuncio
  • darkX
  • alphacube
  • theme1
var win; var id = 0;
function openWindow(className) {
win = new Window('window_id' + id, {
className: className,
title: "Sample",
width:200, height:150}
);
win.getContent().innerHTML = "<h1>Hello World!</h1>";
win.setDestroyOnClose();
win.showCenter();
id++;
}

Open Alert

  • sample
function openAlert() {
Dialog.alert("Hello World!", {
windowParameters: {width:300, height:100},
okLabel: "close",
ok:function(win) {debug("validate alert panel"); return true;} });
}

Services_YouTube

var win;
function openVideo(video_id) {
if (win == undefined) {
win = new Window('window_id', {
className: "dialog", width:445, height:370, zIndex: 100, resizable: true, title: "Sample window", showEffect:Effect.BlindDown, hideEffect: Effect.SwitchOff, draggable:true });
}
win.getContent().innerHTML= '<div style="padding:10px"><object width="425" height="350"><param name="movie" value="http://www.youtube.com/v/' + video_id + '"></param><embed xsrc="http://www.youtube.com/v/' + video_id + '" type="application/x-shockwave-flash" width="425" height="350"></embed></object></div>';
win.showCenter();
}

つか、ちゃんと動くかな。 やっぱり、UIがカコイイといいねー。

Javascriptライブラリ比較

JavaScriptのライブラリの比較についてまとめをdel.icio.usで発見した。ちょっと興味があったので、少しだけまとめておく。
http://www.sitepoint.com/article/javascript-library/2

ここのサイトで取り上げられているのは、次の4つ。

  • Dojo
  • prototype.js + script.aculo.us
  • Mochikit
  • Yahoo! UI Library

なかなかまとまっていて私もだいたいわかった。
実際に使ったことがあるのは、prototype.jsとYUIだけだったけども、著者はMochikitが良さそうってことを書いている。まぁ、もちろんどんなところに使うかによって使うライブラリを分けようって話だったけども。

Dojoは、巨大なライブラリだ。だいたいの機能がそろっていて大規模なJavaScriptアプリを書くに向いている。そのため、ライブラリのファイルサイズも使うことのできるAPIも大きいので、小さなプロジェクトにはおすすめしない。

prototype.js + script.aculo.usは、ドキュメントが一番成熟している。(私の認識と違うけど、最近ドキュメントが充実してきているのかな。。。)そして、現時点で一番広まっているライブラリである。Rubyのイディオムに似ているので、Ruby開発者には問題なく使える。また、Railsで使われているので、バグフィックスとかもはやくていいとのこと。他にもscript.aculo.usやRicoのようなライブラリに使われているので、多くの開発者の選択肢の一つとしてあげられている。でも、イベントハンドリングにおいては、他のライブラリに劣っている。

Mochikitが一番よく設計されていていて、Pythonのイディオムに似ているため、Python使いは問題なく使える。ただ、ドキュメントが足りないと見受けられる点もあって、ちょっと混乱するかもしれないところはイケてない。でも、使い慣れたら、びっくりの連続だ。DOM周り、イテレーション、Ajaxなんて芸術的だぜ。

YUIは、prototype.jsを使うまでもない小さなプロジェクトに向いているとのこと。Ajax、イベント周りの使用方法を簡単に学べるところが魅力だとこと。でも、全体としていかした機能は少ない。

一時期YUIっていいねぇ、と思っていたけど、そうでもないのかな。個人的な意見としては、YUIは、YUIデザパタの実装方法をAPIとして提供したら、一気に評価があがると思う。いつかも書いたけども、Yahoo!は、今までのインターネットポータルサイトを支えてきたサイトなので、UIのノウハウがいっぱいあると思うんだよね。だから、あそこで提唱しているデザパタってかなり使えると思う。現時点では、実装するためにかなり力業を要しないといけない気がするので、私は手をつけていない。APIとして、あのデザパタを提供してくれることを望みます。あまりにも遅いと他のライブラリがそれをAPIとして作ってしまうと思う。

後、最近、symfonyを勉強してたけど、あれもprototype.jsを使っているね。フレームワークとの相性って普及するかどうかって大事だと思うので、prototype.jsがやっぱりいいのかなぁ、なんて思ってみたりもする。

Seleniumがかなり良さげ。

テストツールをいくつか見てみたけども、Seleniumは、ページのシナリオテストに持ってこいだね。かなり便利。Selenium最高!後は、これをうまいことドキュメントに落とすことができるものがあればいいんだがなぁ。

会社では、テスト仕様書などを結局ドキュメントでエクセルか何かで欲しいと言われるので、Seleniumのテストケースでは受け入れてくれない。なので、特定のXMLもしくは、YAMLからSeleniumのHTMLテーブルを作成するってのがあったらいいなぁ。そして、そのXMLかYAMLから印刷可能な形式にしてドキュメントにしちゃうの。そして自動化。個人的にはPDFで吐いてほしい。

もしくは、すでにあるHTMLのテーブルから適当にパースして、マネージャの人が納得するドキュメントを作成できる機能がいいよね。

まぁ、テストやそのドキュメント化の作業はできるだけ自動化してしまいたいので、Seleniumは本当にいい。つーか、気づくの遅いな、ヲレ。
続きを読む

AjaxのonCompleteの処理は、サブクラスに任せる。

そんなことをやってみたので、簡略化して、載せてみる。
で、ファイルは以下のような感じ。面倒なので、全部同じディレクトリにしてみた。
HTMLファイルを見れば、わかるが、prototype.jsを読み込んでから、sample_ajax.jsを読み込む。
おそらく、世間一般に広まっているprototype.js1.3.1では、動かない。まぁ、そんな感じ。

サンプルは「ここ」のページにあります。

  1. sample_ajax.js(下のソース)
  2. prototype.js(1.4.0)
  3. HTMLファイル(sample_ajaxhtml)
  4. Aの読み込み
  5. Bの読み込み

sample_ajax.js

var AjaxParent = Class.create();
AjaxParent.prototype = {

    initialize: function() {
        alert("サブクラスでちゃんと実装してね。");
    },

    /**
      * pathにリクエストを出して、読み込みが終わったら、completeメソッドを呼ぶ。
      *
      * @param path : リクエスト先なのだ。当然のことながら、同じサーバのみね。
      */
    get: function() {
        new Ajax.Request(this.path,
            {
                method       : 'get',
                onFailure    : function(request) {
                    alert("ネットワークへの接続が失敗しました。");
                },
                /** 最後にbindAsEventListenerをちゃんとつけること。 */
                onComplete   : function(request) {
                    var result = request.responseText;
                    this.complete(result);
                }.bindAsEventListener(this, false)
            });
    },

    /**
     * 親クラスでは、誰が何と言おうが、holderは、id=result_pである!
     */
    set_holder: function(holder) {
        this.holder = $('result_p');
    },

    complete: function(result) {
        alert("サブクラスで、ちゃんと実装してね。");
    }
}

/**
 * AjaxParentクラスのサブクラス。
 */
var AjaxChild_A = Class.create();
Object.extend(AjaxChild_A.prototype, AjaxParent.prototype);
Object.extend(AjaxChild_A.prototype, {

    /**
     * 子クラスでinitializeを上書き。
     */
    initialize: function(path) {
        this.path = path;
        alert("AjaxChild_A initialized....");
    },

    /**
     * フィールド
     */
    field: "this is field From AjaxChild_A",

    /**
     * 子クラスで、set_holderを上書き。これは、AjaxChild_Aのみ。
     */
    set_holder: function(holder) {
        this.holder = $(holder);
    },

    /**
     * 子クラスで、completeを上書き。
     * @param response
     */
    complete : function(result) {
        new Insertion.Top(this.holder, "AjaxChild_A: " + result + "<br />");
        alert("AjaxChild_A : " + result);
    }
});

/**
 * AjaxParentクラスのサブクラス。
 */
var AjaxChild_B = Class.create();
Object.extend(AjaxChild_B.prototype, AjaxParent.prototype);
Object.extend(AjaxChild_B.prototype, {

    /**
     * 子クラスでinitializeを上書き。
     */
    initialize: function(path) {
        this.path = path;
        alert("AjaxChild_B Initialized....");
    },

    /**
     * フィールド
     */
    field: "this is field From AjaxChild_B",

    /**
     * 子クラスで、completeを上書き。
     * @param response
     */
    complete : function(result) {
        new Insertion.Top(this.holder, "AjaxChild_B: " + result + "<br />");
        alert("AjaxChild_B : " + result);
    }
});

////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
/**
 * createの引数typeによって、どちらの子クラスを呼ぶかを変える。
 */
var AjaxController = Class.create();
AjaxController.factory = function(type, path, trigger) {
    var my_ajax = eval('new AjaxChild_' + type +'("'+path+'")');
    Event.observe($(trigger), 'click',
                  my_ajax.get.bindAsEventListener(my_ajax), false);
    return my_ajax;
}

sample_ajax.html

<?xml version="1.0" encoding="shift_jis"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="ja" xml:lang="ja" xmlns="http://www.w3.org/1999/xhtml">
 <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <script type="text/javascript" src="prototype.js"></script>
    <script type="text/javascript" src="sample_ajax.js"></script>
    <script language="JavaScript" type="text/JavaScript">
Event.observe(window, 'load', main, false);

function main() {
    /**
     * インスタンスを作ってやってみよう!
     */
    var ajax_test = AjaxController.factory('A', './test_a.txt', 'trigger_a');

    /**
     * ちゃんと子クラスのフィールドにもアクセスできる。
     */
    alert(ajax_test.field);

    /**
     * 同様に、メソッドにもね。
     */
     ajax_test.set_holder('result_a');

    /**
     * インスタンスを作ってやってみよう!
     */
     var ajax_test = AjaxController.factory('B', './test_b.txt', 'trigger_b');

    /**
     * ちゃんと子クラスのフィールドにもアクセスできる。
     */
     alert(ajax_test.field);

    /**
     * メソッドは実装していないので、親のが呼ばれる。
     */
     ajax_test.set_holder('result_b');
}
  </script>
    <title>Ajax Subclass Test</title>
  </head>
  <body>
    <h1>Ajaxのテスト</h1>
    <input type="button" id="trigger_a" value="Ajax_A!" />
    <input type="button" id="trigger_b" value="Ajax_B!" />
    <hr />
    <h2>AjaxChild_Aが実装したのでこっち。</h2>
    <div id="result_a"></div>
    <h2>AjaxChild_Bは未実装なのでここは出力されない</h2>
    <div id="result_b"></div>
    <h2>AjaxParentのメソッドのままだが、AjaxChild_Bは未実装なのでこっち。</h2>
    <div id="result_p"></div>
  </body>
</html>

気になるところは、コメントに書いてみた。onCompleteにbindAsEventListenerをつけないと、thisの値が変わってしまう。これで、一度悩んだ。。。
拡張するときに、プロパティを書き換えるのもなんだか、嫌だけど、しゃーなし。

参考にしたのが次のページ。

IT戦記

 拡張の方法はここを参照させていただきました。prototype.jsと少し拡張の書き方が違うが、やっていることは一緒。prototype.jsでは、次のようにしていたりする。

Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {

naoyaのはてなダイアリー

 ここを見て、動的にクラス名を決定するところで、evalを使うようにした。次のような感じ。

 var test_class = eval('new ' + classname);

llameradaの日記

こども(てれび)

 上の二つを見て、thisがどっかいっちゃうところを修正した。AjaxのonCompleteにbindAsEventListenerをくっつけるところは、ここで、勉強しました。

Using prototype.js v.1.4.0

 1.4.0を対象にしていたので。
続きを読む

少しばかりAjaxな辞書ツール作った。

英辞郎に飛ばすBookmarkletとかあるけども、あまりページを遷移したくないなぁ、という風に前から思っていた。

だって、何かの文章を読んでいるときに、一つわからない単語があって、Bookmarkletで訳を見るまではいいけども、その前の文章に戻ってきた際(戻るのもウザイ)、どこを読んでいたかわからなくなることがよくある。なので、ページの中に訳が出てきたらいいなぁ、なんて思ってみる。

Google Toolbarのマウスオーバー辞書ってのもあるんだけど、なんかひっかからないのが多くてちょっと嫌。イメージでは、こんな感じなんだけどなぁ。で、何かないかなぁ、と考えていたが、調べてもないので、ブログをやり始めた頃に考えていたものを自分で作ってみることにした。

仕組みは簡単なので、誰でも簡単に作ることができると思うけど、なんで無いのかなぁ。ドイツ語と英語のやつはあったのに。ということでおうちでプログラミング。まぁ、作るのめんどくせーな、と思ってたけども、少しだけやる気になってみた。まぁ、perlのお勉強ですわ。

で、作ったものが、Ajaxな英和/和英辞書。
って、別にAjaxでなくても、ボタンでポチットな、でよかったのだが。prototype.jsでも使ってみるか、と思っていてせっかくだったので、Ajaxな動きを取り入れてみた。

辞書ファイルは、EDICTを使用した。xyzzyでは、私も使っているけどもいい辞書ですね。そして、その辞書の検索には、私の学部時代の師匠が作った検索システムDiqtを使用させていただいた。で、それを学校の研究室のサーバにインストールをした。Diqtサーバは、そのまんま。XML RPCサーバにしてもいいかな、と思ったけどもとりあえず、自分のためだけのツールということでいじることは辞めた。気が向いたらするかも。

で、処理としては、JavaScriptで網掛け部分を取得し、マウスアップしたら網掛け部分をパラメータとしてリクエストを飛ばす。そのリクエストを受け取るサーバ(Diqtサーバのクライアント)は、受け取ったパラメータを加工して、DiqtサーバにHTTPリクエストを投げる。Diqtサーバからのレスポンスを、また少し加工して、JavaScriptのリクエストに対するレスポンスとして返す。そして、そのレスポンスを表示したい場所に入れる、と。

これで、網掛けに選択した言葉を瞬時に同じページに出力することができた。Ajaxの使用用途でこれは、間違ってないかな。あまり鬱陶しいインタフェースは使ってないし。ただ、リクエスト飛ばしすぎになってしまうのではないか、とちょっと思ってみる。

で、早速、このツールを自分のブログに当てはめてみる。どこでもいいが、選択すると、もし選択した単語に対応する訳があれば、それを右のメニューのDYNAMIC DIQTの下に出力する。半角英数を選択すれば、訳は日本語で。日本語を選択すれば、訳は英語が出るようにした。まぁ、悪くないね。もう少し整理したら、簡単なやり方とサンプルを MY WORKに置こうかな。

つか、なんで、Diqtサーバが別の環境を使っているかというと、今のレンタルサーバでは、容量50Mだし、Cで書かれたCGIスクリプトとか動かないだろうから。別にサーバに余裕があって、いろいろインストールできるのだったら、同じサーバでもいいか。

うーん。でも、こんなもの作りなんてすぐ終わっちゃうよね。もう少し規模の大きめなものを作りたいなぁ。
まぁ、CPANのLWP, TokeParserの使い方を勉強したから、これはこれでいいか。

つか、絵を描かないと、文章だけじゃ何を言っているかわからんかな。
続きを読む

Shin Ohno 2003-2012