H2Databaseを追っかけていたりしたブログ

H2 database のリリースノートを読んだりとか。

dojo toolkitやってみる 2

dojoのドキュメントを読んでいたら、dojo/aspectなんていうAOPのためのモジュールがあったので試してみます(Javaではおなじみですね。他の言語でどうなのかよく知りません)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Tutorial: Hello Dojo!</title>
  </head>
  <body>
    <h1 id="greeting">Hello</h1>
    <h1 id="greetingJa">こんにちは</h1>
    <!-- load Dojo -->
    <script src="dojo/dojo.js"
      data-dojo-config="async: true"></script>
    <script>
      require(['dojo/dom','dojo/aspect','dojo/domReady!'], function(dom,aspect){
        var signal = aspect.after(/*対象のオブジェクト*/dom, /*function名*/'byId', /*対象のオブジェクトのfunctionが実行された後に実行するfunction=advise*/function(el){
          //これは元のfunctionの返り値を返すだけなので特に意味がない。
          return el;
          //例えば下記のように返り値を差し替えることができる
          //return document.getElementById('greetingJa');
          //下記のようにするとまたこのAdvisingFunctionが発動してしまい、スタックを使い果たしてしまう
          //return dom.byId('greetingJa');
        });
        var x = dom.byId('greeting');
        x.innerHTML += ' World';
      });
    </script>
  </body>
</html>

上記のような感じで、使う事が出来ます。上で使っているのは、元のfunctionが実行された後に発動するafterですが、その他にbeforeとaroundの計3つのfunctionがこのdojo/aspectパッケージでは提供されています。

after,before,aroundいずれもremoveというfunctionのみを持つオブジェクトが返ります(APIドキュメントではsignalオブジェクトとなっている)。そのremoveを実行する事で、それ以降adviseを無効にする事が出来ます。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Tutorial: Hello Dojo!</title>
  </head>
  <body>
    <h1 id="greeting">Hello</h1>
    <h1 id="greetingJa">こんにちは</h1>
    <!-- load Dojo -->
    <script src="dojo/dojo.js"
      data-dojo-config="async: true"></script>
    <script>
      require(['dojo/dom','dojo/aspect','dojo/domReady!'], function(dom,aspect){
        var signal = aspect.after(dom, 'byId', function(el){
          return document.getElementById("greetingJa");
        });
        var x = dom.byId('greeting');
        x.innerHTML += ' World';

        //adviseを無効化
        signal.remove();

        x = dom.byId('greeting');
        x.innerHTML += ' World';
      });
    </script>
  </body>
</html>

なお、APIドキュメントを見ると、before,aroundについてはsignalを返すことが明示されていませんが、after同様signalを返します。

beforeは以下のように使います。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Tutorial: Hello Dojo!</title>
  </head>
  <body>
    <h1 id="greeting">Hello</h1>
    <h1 id="greetingJa">こんにちは</h1>
    <!-- load Dojo -->
    <script src="dojo/dojo.js"
      data-dojo-config="async: true"></script>
    <script>
      require(['dojo/dom','dojo/aspect','dojo/domReady!'], function(dom,aspect){
        aspect.before(dom, 'byId', function(id){
          //明示的に返り値を返さなかった場合、元のfunctionは元の引数で実行される
          //下記のように配列で値を返してやると、元のfunctionはここで返した値で実行される
          //return [id + 'Ja'];
        });
        var x = dom.byId('greeting');
        x.innerHTML += ' World';
      });
    </script>
  </body>
</html>

簡単に使えて、面白いですね。