« 2007年2月 | トップページ | 2007年4月 »

2007年3月の13件の記事

2007年3月31日 (土)

ドラッグ&ドロップ

Dojoのドラッグ&ドロップ機能を用いるときは、"dojo.dnd.*"をrequireする。

dojo.require("dojo.dnd.*");

利用するときは、ドラッグ&ドロップするHTML要素を指定する。HTMLとしての記述は特にない。 ドラッグ対象となるオブジェクト(HTML要素)をHtmlDragSourceとして設定する。 ドラッグしたオブジェクトをドロップする場所を、HtmlDropTargetとして設定する。

ドロップできる場所では、水平の線が現れる。ドラッグしたオブジェクトを、ドロップ対象ではない場所でドロップしたら、ドラッグしたオブジェクトは元の場所に戻る。

HtmlDragSource/HtmlDropTargetの引数として、1つ目にドラッグ対象となるオブジェクト、2つ目にドラッグ/ドロップ対象の範囲を示すコードを指定する。HtmlDragSourceではコードを文字列として1つ、HtmlDropTargetではコードを配列で複数指定できる。

以下の例では、aaa, bbb, cccをドラッグして、ddd, eeeにドロップできる。

     
  • aaa
  • bbb
  • ccc
    • ccc-1
    • ccc-2
  • ddd
  • eee
<html>
  <head>
    <title>Dojo Demos</title>
    <script type='text/javascript' src='dojo.js'></script>
    <script type='text/javascript'>
      dojo.require('dojo.dnd.*');
      
      function init() {
        new dojo.dnd.HtmlDropTarget(dojo.byId('ddd'), ['dest']);
        new dojo.dnd.HtmlDropTarget(dojo.byId('eee'), ['dest']);

        new dojo.dnd.HtmlDragSource(dojo.byId('aaa'), 'dest');      
        new dojo.dnd.HtmlDragSource(dojo.byId('bbb'), 'dest');
        new dojo.dnd.HtmlDragSource(dojo.byId('ccc'), 'dest');
      }

      dojo.addOnLoad(init);
    </script>
  </head>
  <body>
    <ul>
      <li id='aaa'>aaa</li>
      <li id='bbb'>bbb</li>
      <li id='ccc'>ccc
        <ul>
          <li>ccc-1</li>
          <li>ccc-2</li>
        </ul>
      </li>
    </ul>
    <ul>
      <li id='ddd'>ddd</li>
      <li id='eee'>eee</li>
    </ul>
  </body>
</html>

HtmlDragMoveSourceを使うと、ドラッグ&ドロップではなく、指定したHTML要素を自由に動かすことができる。 HtmlDragMoveSourceを使うときは、dojo.dnd.HtmlDragMoveをrequireする。コンストラクタの引数にはHTML要素のみを指定する。

以下のfffは自由に動かすことが出来る。

 

  • fff
dojo.require('dojo.dnd.HtmlDragMove');

function init() {
new dojo.dnd.HtmlDragMoveSource(dojo.byId('fff'));
}
dojo.addOnLoad(init);

setDragHandleでドラッグできる場所を指定できる。disableSelectionでは、ドラッグできない場所を指定できる。

var drag = new dojo.dnd.HtmlDragSource(dojo.byId('outer1'));
drag.setDragHandle(dojo.byId('inner1'));

dojo.html.disableSelection(dojo.byId('inner1'));

イベント

ドラッグ&ドロップのイベントを取得する方法として、既存のクラス(dojo.dnd.HtmlDropTargetなど)を継承したクラスを利用する方法と、dojo.event.connectを使う方法とがある。

ドロップ対象において発生するイベントには以下がある。

  • onDrop(e) ドラッグ対象をドロップしたとき
  • onDragOver(e) ドロップ対象の上に、ドラッグ対象が入ったとき
  • onDragOut(e) ドロップ対象の上から、ドラッグ対象が出たとき
  • onDragMove(e) ドラッグ対象の上で、ドラッグ対象を動かしたとき (うまく動きませんできた)
  • onDropStart(e) ドラッグが始まったとき。ドロップ対象の検証をするときに使える
  • onDropEnd(e) ドラッグが終わったとき

各イベントでは、引数としてdojo.dnd.DragEventオブジェクトを受け取る。DragEventオブジェクトは以下のプロパティを持つ。

  • dragObjects: ドラッグしたオブジェクト
  • dragSource: ドラッグ対象のオブジェクト。dragSource.dragObjectはdragObjectと同じ。ドロップ先の情報もパラメータとして持つ。
  • target: ドロップ対象のオブジェクト。まだドロップしてなければnullが返る。

ドラッグ対象のイベントには以下がある。

  • onSelected(e) ドラッグ対象がクリックされたとき
  • onDragStart(e) ドラッグを始めたとき
  • onDragEnd(e) ドラッグが終わったとき。ドロップ対象のイベントonDropの前に呼ばれる。

以下の例では、ドロップ対象の上にドラッグ対象が重なったら、ドロップ対象の色を赤色に変えるようにしている。

  • ggg
  • hhh
  • iii
    • iii-1
    • iii-2
  • jjj
  • kkk
<html>
<head>
  <title>Dojo Demos</title>
  <script type="text/javascript">
    var djConfig = { isDebug: true };
  </script>
  <script type="text/javascript" src="dojo.js"></script>
  <script type="text/javascript">
    dojo.require("dojo.dnd.*");
      
    function init() {
      dojo.declare("dojo.dnd.DestDropTarget",dojo.dnd.HtmlDropTarget,{
        onDragOver: function(e) {
          dojo.debug('dragOver');
          this.domNode.style.color = "red";
          return dojo.dnd.HtmlDropTarget.prototype.onDragOver.apply(this, arguments);
        },
        onDragOut: function(e) {
          dojo.debug('dragOut');
          this.domNode.style.color = "black";
          return dojo.dnd.HtmlDropTarget.prototype.onDragOut.apply(this, arguments);
        }
      });
      
      new dojo.dnd.DestDropTarget(dojo.byId("ddd"), ["dest"]);
      new dojo.dnd.DestDropTarget(dojo.byId("eee"), ["dest"]);

      new dojo.dnd.HtmlDragSource(dojo.byId("aaa"), "dest");      
      new dojo.dnd.HtmlDragSource(dojo.byId("bbb"), "dest");
      new dojo.dnd.HtmlDragSource(dojo.byId("ccc"), "dest");
    }

    dojo.addOnLoad(init);
  </script>
</head>

<body>
  <ul>
    <li id="aaa">aaa</li>
    <li id="bbb">bbb</li>
    <li id="ccc">ccc
      <ul>
        <li>ccc-1</li>
        <li>ccc-2</li>
      </ul>
    </li>
  </ul>
  <ul>
    <li id="ddd">ddd</li>
    <li id="eee">eee</li>
  </ul>

 </body>
</html>

以下の例では、xxx, yyy, zzzをドラッグして、入力フォームに値を設定できる。  

  • xxx
  • yyy
  • zzz

<html>
<head>
  <title>Dojo Demos</title>
  <script type="text/javascript" src="dojo.js"></script>
  <script type="text/javascript">
    dojo.require("dojo.dnd.*");
    
    function init4() {
      dojo.declare("dojo.dnd.DestDropTarget",dojo.dnd.HtmlDropTarget,{
        onDragOver: function(e) {
          dojo.byId('text').value = e.dragObjects[0].domNode.innerHTML;
        }
      });
      
      new dojo.dnd.DestDropTarget(dojo.byId("text"), ["dest"]);

      new dojo.dnd.HtmlDragSource(dojo.byId("xxx"), "dest");      
      new dojo.dnd.HtmlDragSource(dojo.byId("yyy"), "dest");
      new dojo.dnd.HtmlDragSource(dojo.byId("zzz"), "dest");
    }

    dojo.addOnLoad(init4);
  </script>
</head>

<body>
<ul>
<li id="xxx">xxx</li>
<li id="yyy">yyy</li>
<li id="zzz">zzz</li>
</ul>

<input id="text" type="text">

</body>
</html>

2007年3月28日 (水)

スタイル

スタイル情報の取得および設定をするときは、dojo.html.layoutをrequireする。

dojo.require("dojo.html.layout");

サイズ

HTML要素のオブジェクトまたはHTML要素のIDを文字列と指定して、 以下の3つのサイズを得ることができる。 dojoのwidgetオブジェクトを渡しても結果はNaNが返る。

     
  • content: コンテンツ自身のサイズ
    • dojo.html.getContentWidth(obj)/ dojo.html.getContentHeight(obj)
  • inner: content + padding + borderのサイズ
    • dojo.html.getOuterWidth(obj) / dojo.html.getOuterHeight(obj)
  • outer: content + padding + border + marginのサイズ
    • dojo.html.getInnerWidth(obj) / dojo.html.getInnerHeight(obj)

以下のように幅と高さを持つオブジェクト一緒に返すこともできる。

var c= dojo.html.getMarginBox(obj)/getBorderBox(obj)/getContentBox(obj);
c.width;
c.height;

サイズを取得するだけでなく、サイズを設定することもできる。

dojo.html.setMarginBox(obj, { width: 110, height: 60 });

位置情報

dojo.html.getAbsolutePosition(obj, boolean)により、指定したHTML要素の絶対位置を得られる。2つ目の引数では、trueを指定するとbody要素内における絶対位置を返す。falseを指定するとウィンドウ枠内の表示位置における絶対位置を返す。

trueのときは、body要素内の絶対位置であるため、ウィンドウのスクロールバーの位置に関係なく同じ値となる。falseのときは、ウィンドウのスクロールバーの位置によって、表示されるHTML要素の位置が変わる。

var pns = dojo.html.getAbsolutePosition(obj, false);
var pws = dojo.html.getAbsolutePosition(obj, true);
pns.x; // X座標
pns.y; // Y座標

dojo.html.getScrollLeft()/Top()により、ウィンドウのスクロールバーのスクロール位置を返す。 dojo.html.getScroll()を使ったときは、

var scroll = dojo.html.getScroll();
scroll.left;
scroll.top;

表示のON/OFF

指定したHTML要素の表示をON/OFFと切り替える。setShowing/show/hide/setDisplayを用いたときは、CSSのdisplayプロパティでnoneを指定するかしないかを切り替える。setVisibilityを用いたときは、CSSのvisibilityプロパティをvisible/hiddenに切り替える。

displayプロパティでnoneを指定すると、HTML要素自体がなくなる。一方、visibilityをvisible/hiddenに切り替えたときは、表示しないだけで、指定したHTML要素はなくならない。そのため、visibilityを切り替えてもページ全体のレイアウトは変わらない。

表示をONにする。

dojo.html.setShowing(obj, true);
dojo.html.show(obj);
dojo.html.setDisplay(obj, true);
dojo.html.setVisibility(obj, true);
dojo.html.setVisibility(obj, '');

表示をOFF/非表示にする。

dojo.html.setShowing(obj, false);
dojo.html.hide(obj);
dojo.html.setDisplay(obj, false);
dojo.html.setVisibility(obj, false);
dojo.html.setVisibility(obj, 'hidden');

表示されているかどうかをチェックする。isShowingとisDisplayedのときは、displayプロパティがnoneかどかをチェックする。ただし、visibility: visibleのときは、display:visibleでもtrueとなる。isVisibleは、visibilityがvisibleかhiddenかをチェックする。このときは、display:noneでもvisibility: visibleのときはtrueになる

dojo.html.isShowing(obj); 
dojo.html.isDisplayed(obj);
dojo.html.isVisible(obj);

以下のtoggleXXXでは、表示されているときは非表示、表示されていないときは表示に切り替える。

dojo.html.toggleShowing(obj);
dojo.html.toggleDisplay(obj);
dojo.html.toggleVisibility(obj);

CSSの追加

insertCssTextを用いてCSSを追加できる。
dojo.html.insertCssText("table{ background-color: red;}");
insertCssFileを使うことで、リンクするCSSファイルを追加することもできる。
dojo.html.insertCssFile("./css/test.css");

2007年3月25日 (日)

ローカルディスクへのデータ保存

dojo.storageを使うことでクライアント側にデータを保存して利用することができる。一般的に、ブラウザ側の保存領域として使うことができるCookieでは数kbyteまでしか保存できないが、dojo.storageではクライアントPCのディスク容量の限りデータを保存できる。

クライアントにデータを保存することで、サーバとのやりとりを減らすことができ、作業の中断をいつでもできるようになる。また、Webベースで提供されているOfficeアプリケーションをオフラインでも動作させることができるようになる。

dojo.storageでは、データの保存とアクセスは、単純なHashテーブルとしてアクセスできる。

dojo.storageを利用するときは、dojo.storage.*とdojo.event.*をrequireする。

dojo.require("dojo.event.*");
dojo.require("dojo.storage.*");

dojo.storageの処理は、dojo.storageがinitializeされてから、実行するようにする。以下の例では、TestStorageオブジェクトのinitializeメソッドにおいてdojo.storageにアクセスして初期化処理(データの取得)をしている。

if(dojo.storage.manager.isInitialized() == false){
dojo.event.connect(dojo.storage.manager, "loaded", TestStorage,
                  TestStorage.initialize);
}else{
dojo.event.connect(dojo, "loaded", TestStorage, TestStorage.initialize);
}

データを取り出すときは、dojo.storage.get(key)を用いる。

var results = dojo.storage.get(key);

データを保存するときは、dojo.storage.put(key, value, saveHandler)を用いる。

try{
  dojo.storage.put(key, value, saveHandler);
}catch(exp){
  alert(exp);
}

valueは、文字列だけでなく、JavaScriptのオブジェクトを指定できる。ローカルファイルに保存するときには、内部でJSON形式の文字列に変換している。

saveHandlerには、保存した後のコールバック関数を指定する。saveHandlerは保存が失敗したかどうかを受け取る。2つの引数を取り、1つ目はstatusで以下の3つの値のどれかとなる。

  • dojo.storage.SUCCESS - 保存に成功
  • dojo.storage.FAILED - ユーザが保存を拒否した
  • dojo.storage.PENDING - ユーザは保存の可否を指定するUIプロンプトを表示している

2つ目の引数は、保存されたkeyNameである。保存は非同期なので、どのkeyが保存されたのかをコールバックで知りたいときもある。以下に、saveHandlerの例を示す。

var saveHandler = function(status, keyName){
  if(status == dojo.storage.PENDING){
     // ... 
  }else if(status == dojo.storage.FAILED){
     // ...
  }else if(status == dojo.storage.SUCCESS){
     // ...
  }
}

dojo.storage.getKeys()を使うと利用できるキーの一覧を取得できる。

var availableKeys = dojo.storage.getKeys();

dojo.storageにより保存された情報は、Cookieと同じく保存時と同じドメインにおいてのみアクセスできる。他のドメインからはアクセスできない。

以下の例は、ボタンを押すと入力フォームの値をローカルファイルに保存する。ブラウザを開いたら、過去に保存した値を入力フォームに戻している。

<html>
  <head>
    <title>Dojo Demos</title>
    <script type="text/javascript" src="dojo.js"></script>
    <script type="text/javascript">
dojo.require("dojo.event.*");
dojo.require("dojo.storage.*");
dojo.require("dojo.widget.Button");

function buttonPressed(event){
  try{
    dojo.storage.put('inputtext', dojo.byId('inputtext').value, saveHandler);
  }catch(exp){
    alert(exp);
  }
}

var saveHandler = function(status, keyName){
  if(status == dojo.storage.PENDING){
     // ...
  }else if(status == dojo.storage.FAILED){
     // ...
  }else if(status == dojo.storage.SUCCESS){
     // ...
  }
}
      
var TestStorage = {
  initialize: function(){
    if(dojo.storage.get('inputtext')){
      dojo.byId('inputtext').value = dojo.storage.get('inputtext');
    }
  }
}
      
function init(){
  var saveButton = dojo.widget.byId('saveButton');
  dojo.event.connect(saveButton, 'onClick', 'buttonPressed');
      
  if(dojo.storage.manager.isInitialized() == false){
    dojo.event.connect(dojo.storage.manager, "loaded", TestStorage,
                    TestStorage.initialize);
  }else{
    dojo.event.connect(dojo, "loaded", TestStorage, TestStorage.initialize);
  }
}

dojo.addOnLoad(init);
    </script>
  </head>
 
  <body>
    <input type="text" id="inputtext" />
    <button dojoType="Button" widgetId="saveButton">Press Me</button>
  </body>
</html>

2007年3月24日 (土)

配列

dojo.langに含まれる配列に関する関数を説明する。

dojo.lang.isArray()は、配列かどうかをチェックする。空の配列も、trueとなる。

dojo.lang.isEmpty()で、配列を引数に渡すと、配列が空かをチェックする。空の配列は、isEmpty()ではtrueとなる。

dojo.lang.find()は、配列の中に指定したオブジェクトが何番目含まれるかを返す。以下の例では2を返す。

var foo = new Array(128, 256, 512);
dojo.lang.find(foo, 512);

dojo.lang.forEach()を使うことで、配列の全ての要素に同じ関数を適用できる。

var colors = ["red", "white", "blue"];
dojo.lang.forEach(colors, alert);

dojo.lang.map()では、配列の全ての要素に同じ関数を適用して、その結果を配列で受け取ることができる。以下の例では、2乗した値の配列 [1,4,9,16,25]を返す。

var integers = [1,2,3,4,5];
var squares = dojo.lang.map(integers, function(x){ return x*x; });

dojo.lang.every()は、配列の全ての要素に対して、指定した関数を適用した結果が全てtrueになるかどうかを返す。1つでもfalseがあったときはfalseを返す。以下の例はtrueを返す。

var integers = [1,2,3,4,5];
var result = dojo.lang.every(integers, function(x){ if (x <10) return true; return false;});

dojo.lang.some()は、配列の要素に対して指定した関数を適用して、1つでもtrueになればtrueを返す。全てfalseのときはfalseを返す。以下の例をtrueを返す。

var integers = [1,2,3,4,5];
var result = dojo.lang.some(integers, function(x){ if (x == 3) return true; return false;});

配列の比較

dojo.collections.Setには、2つの配列を比較するメソッドが提供される。

メソッド名概要
difference(arrayA, arrayB) 引数として指定した2つの配列が全て同じかどうか
intersection(arrayA, arrayB) arrayAの全ての要素がarrayBに含まれないかどうか
isSubSet(arrayA, arrayB) arrayBがarrayAの部分集合がどうか
isSuperSet(arrayA, arrayB) arrayBがarrayAを含んでいるかどうか
union(arrayA, arrayB) arrayAとarrayBを結合した配列を返す

JavaScriptの配列

参考に、JavaScriptの配列が元々持つメソッドを以下に示す。

メソッド名概要
concat(ary2) aryとary2を連結した配列を返す。引数の配列は複数指定することもできる
join('str') 引数の文字列で配列の各要素を繋げた文字列を返す。引数を省略したときはカンマ(,)で連携する
length 配列の要素数を返す
pop() 配列の最後の要素を取り除く
push(e1) 配列の最後に引数の要素を追加する。引数の要素を複数指定することもできる
reverse 逆順に並び替えた配列を返す
shift() 配列の最初の要素を削除して、その要素を返す
splice(start, end) start~endまでの要素を抜き出した配列を返す。引数のendは省略できる
sort ソートした配列を返す
toString() 文字列に変換した結果を返す
unshift(e1) 配列の最初に引数の要素を追加する。引数の要素を複数指定することもできる

ブラウザのバックボタン/履歴への対応

バック/フォワードボタンへの対応

Ajaxによりデータを取得して画面の一部を書き換えた場合、ブラウザのバックボタンを押しても画面の一部の書き換えを元に戻すことはできない。間違ってバックボタンを押すと、これまでの操作内容は失われてしまう。

画面の一部を書き換えただけでは、ブラウザの履歴(history)、URLを更新しないためである。

dojo.undo.browser を使うことで、Ajaxアプリケーションにおいてもブラウザのバック/フォワードボタンを利用することができるようになる。dojo.undo.browserでは、バック/フォワードボタンの通知を受けて動作するオブジェクト/関数を指定することで、ブラウザのバック/フォワードボタンに対応できるようになる。

dojo.undo.browserを利用するには、まず、djConfigで、preventBackButtonFix: falseを指定する。これにより隠れたiframeが追加される。

次に、dojo.require("dojo.undo.browser"); を指定し、dojo.undo.browser.setInitialState(state)により初期状態を設定する。以降は、ブラウザの履歴に追加するタイミングで、dojo.undo.browser.addToHistory(state)を呼び出す。ここで、stateオブジェクトには、バック/フォワードボタンが押されたときに呼ばれるメソッドを指定する。

バックボタンの通知を受けるには、stateオブジェクトに、back(), backButton(), handle(type)のいずれかのメソッドを定義する。typeには、"forward"または"back"が指定される。

フォワードボタンの通知を受けるには、forward(), forwardButton() or handle(type)のメソッドいずれかを定義する。

簡単なstateオブジェクトの例をあげる。

var state = {
back: function() { alert("Back was clicked!"); },
forward: function() { alert("Forward was clicked!"); }
};

dojo.io.bindを使って、画面を書き換えているのであれば、dojo.io.bindを呼び出すタイミングで、その情報をstateオブジェクトに入れることで、バックボタンが押されたときに、状態を元に戻すような動作を行うことが可能になる。

URL

dojo.io.bindを使うことで、ブラウザのロケーションバーのURLを変えることもできる。URLを指定するには、stateオブジェクトのchangeUrlプロパティを使う。

changeUrlプロパティの値としてstringを指定したときは、Urlの最後に#の後に続けて、指定した値が入る。 changeUrlプロパティの値としてtrueを指定すると、dojoが自動的にユニークな値を設定する。

ブラウザの状態を示す情報をURLに指定して、URLが指定されたら状態を復元ようにすることで、ユーザはブックマークに状態を追加したり、他の人にブラウザの状態を伝えることができるようになる。

同じ値をchangeUrlに続けて含むstateオブジェクトを渡したときは、ブラウザの履歴には1つのstateオブジェクトだけが残る。

addToHistory()を呼び出すときにchangeUrlを使うときは、必ずchangeUrlを使うようにしなければならない。changeUrlを使わないaddToHistory()呼び出しが含まれていると正しく動作しない。

サンプルコード

<html>
  <head>
    <title>Dojo Demos</title>
    <script type="text/javascript">
      var djConfig = { isDebug: true, preventBackButtonFix: false };
    </script>
   
    <script type="text/javascript" src="dojo.js"></script>
    <script type="text/javascript">
dojo.require("dojo.lang.declare");
dojo.require("dojo.undo.browser");

function buttonPressed(){
  dojo.byId('message').innerHTML = 'buttonPressedが押されました。';
  dojo.undo.browser.addToHistory(new State('button 1'));
}

function buttonPressed2(){
  dojo.byId('message').innerHTML = 'buttonPressed2が押されました。';
  dojo.undo.browser.addToHistory(new State('button 2'));
}      

function init(){
  dojo.declare("State", null, {
    initializer: function(name){
      this.name=name;
    },
    back: function() {
        dojo.debug("Back was clicked in "+this.name);
    },
    forward: function() {
        dojo.debug("Forward was clicked in "+this.name);
    }
  });
      
  dojo.undo.browser.setInitialState(new State("initial"));

  var historyButton = dojo.byId('historyButton');
  var historyButton2 = dojo.byId('historyButton2');
  dojo.event.connect(historyButton, 'onclick', 'buttonPressed');
  dojo.event.connect(historyButton2, 'onclick', 'buttonPressed2');
}

dojo.addOnLoad(init);
    </script>
  </head>
 
  <body>
    <button id="historyButton">Press Me 1</button>
    <button id="historyButton2">Press Me 2</button>
    <div id="message"></div>
  </body>
</html>

2007年3月21日 (水)

publish/subscribe

異なるメソッド間で連携する手段として、publish/subscribeメソッドが用意されている。publish/subscribeを用いた場合、共通のtopic名を指定することで、直接やり取りする相手を明示せずに呼び出すことができる。 topic名を指定してpublishを実行すると、同じtopic名を指定して実行しているsubscribeメソッドが呼ばれる。同じtopic名に対してsubscribeされる先は複数設定できる。

subscribeを実行するときは、topic名以外に、同じtopic名でpublishが実行されたときに実行されるオブジェクトとそのメソッド名を指定する。 publishを実行するときは、topic名と、subscribeで指定したオブジェクトのメソッドが実行されるときに渡す値を指定する。

var foo = new function() {
    this.init = function() {
        dojo.event.topic.subscribe("/mytopic", this, processMessages);
    }

    function processMessages(message) {
        alert("Message: " + message.content);
   }
}

var bar = new function() {
    this.showMessage = function(message) {
        dojo.event.topic.publish("/mytopic", {content: message});
    }
}

foo.init();
bar.showMessage("Hello Dojo Master");

同じオブジェクト内の

上記の例では、topic名として "/mytopic"を指定して、publish/subscribeが実行されている。 foo.init()によりsubscribeがまず実行された後、bar.showMessageによりpublishが実行され、subscribeの実行時に指定したオブジェクトのメソッドが呼ばれる。

publishを実行したとき、contentプロパティの値としてshowMessageが呼ばれたときの引数を指定している。 subscribeで指定したprocessMessagesメソッドでは、引数オブジェクトのcontentプロパティとして値を受け取っている。

HTML要素の取得

WidgetId

DojoのWidgetオブジェクトを取得するには、dojo.widget.byId()を使う。 例えば、以下のようにwidgetIdとして'foo'を指定したときは、

<div widgetid="foo" dojotype="datepicker"> 

'foo'を引数に指定してDojo Widgetオブジェクトを取得できる。

var foo = dojo.widget.byId('foo');

Id

通常のHTML Elementを取得するAPIは、dojo.byId()として用意されている。

<input type="button" value="ボタン" id="bar" />

上記のボタンのElementは、以下のように取得できる。

var bar = dojo.byId('bar');

取得するHTML Elementの範囲を指定するときは、dojo.byId(doc, 'bar')のように、第一引数で範囲を指定するHTML Elementを指定する。

DojoのWidgetは、表示されたときのHTML要素と異なる場合があるためdojo.widget.byIdを用いてwidgetidを指定して取得する必要がある。dojo.byIdとは動作が異なるので注意が必要。

クラス名

dojo.html.getElementsByClassName()を用いて、クラス名を指定してHTML要素を取得することもできる。

 

<div class="sample">1</div>
<div class="sample">2</div>

以下の例で、上記の2つのdiv要素を取得できる。

dojo.require("dojo.html.style");

dojo.html.getElementsByClassName('sample')

2007年3月16日 (金)

関数の呼び出しイベント

dojo.event.connect("after", exampleObj, "foo", exampleObj, "bar");

のように記述することで、exampleObj.foo()が呼ばれると、続けてexampleObj.bar()を呼び出すようになる。"after"ではなく "before"と書くと、exampleObj.foo()を呼びだすと、foo()が実行される前にexampleObj.bar()が実行されてから、foo()が実行される

Dojoの関数に対して処理を追加したいときなど、既存のコードに処理を追加するときなどに使える。

var o = new Object();
o.init = function (){alert('a');};
o.next = function (){alert('b');};

dojo.event.connect("before", o, "init", o, "next");

この例では、initを呼びだすと、initが実行される前にnextが実行されてから、initが実行される。

最初の引数 "before" または  "after"が省略されると、"after"として処理される。

以下のようにobjectの指定なしで、記述することもできる。この場合は、func1を呼び出すと、その後にfunc2が呼ばれる。

dojo.event.connect("func1", "func2");

引数

引数を指定して関数を呼び出したときは、両方の関数に同じ引数が渡される。

after, beforeではなく、aroundを指定することで、関数が呼ばれる前に引数をいじることができる。以下の例では、helloPressed('a','b')と呼び出されいるが、argSwapAroundAdviceで、1つ目と2つ目の引数の順番を入れ替えて、3つ目の引数として'c'を追加している。

function helloPressed(message, message2, message3){
  dojo.debug('Hello World! '+message+', '+message2+', '+message3);
}

function argSwapAroundAdvice(miObj){
  var tmp = miObj.args[1];
  miObj.args[1] = miObj.args[0];
  miObj.args[0] = tmp;
  miObj.args[2] = 'c';
  ret = miObj.proceed();
  return ret;
}

function init(){
  helloPressed('a', 'b');
}
dojo.event.connect('around', 'helloPressed', 'argSwapAroundAdvice');
dojo.addOnLoad(init);

aroundにより、helloPressedが呼び出される前に、argSwapAroundAdviceが呼ばれる。argSwapAroundAdviceは、引数として、helloPressedを呼び出したときの引数をargs配列として受け取る。このargsを変更して、最後にproceed()を呼び出して、returnする。

2007年3月14日 (水)

クラス/オブジェクト

クラスの作成

クラスを作成するに、dojo.declare()を用いることができる。dojo.declare()を用いるときは、事前にdojo.require('dojo.lang.declare')を宣言しておく。

dojo.declare("ClassName",null, {
  //class body
});

ClassNameには、my.class.ClassNameのように「.」を含めて、パッケージ名のように指定できる。

以下の例では、initializerとmoveToNewCityメソッドを含むPersonクラスを定義している。initializerメソッドがコンストラクタとなる。

dojo.declare("Person", null, {
    //acts like a java constructor
    initializer: function(name, age, currentResidence){
      this.name=name;
      this.age=age;
      this.currentResidence=currentResidence;
    },
    moveToNewCity: function(newState) {
      this.currentResidence=newState;
    }
});

このクラス定義を用いて、インスタンス化するには、以下のようにinitializerメソッドの引数を指定する。initializerメソッドは、オブジェクトが作られたときに一度だけ呼ばれる。

var matt= new Person('Matt', 25, 'New Mexico');

dojo.declare()において、2つ目の引数で、継承するクラスを指定することができる。以下の例では、Personクラスを継承してEmployeeクラスを宣言している。

dojo.declare('Employee', Person, {
    //acts like a constructor
    initializer:function(name, age, currentResidence, position){
      Employee.superclass.initializer(name, age, currentResidence);
      this.password=';
      this.position=position;
    },

    login: function(){
      if(this.password!='' && this.password!=null){
        alert('you have successfully loged in with the password '+this.password);
      }else{
        alert('please ask the administrator for your password');
      }
    }
});

Employee.superclass.initializerにより、Personクラスのinitializerを呼んでいる。

親クラスをのプロパティを参照するときは、superclassを指定する。配列やオブジェクトをプロパティとして用いるときは、initializerで宣言することが必要となる。プロパティの値として直接宣言することはできない。

オブジェクトに関連したメソッド

オブジェクトのメソッド呼び出しに関する関数dojo.lang.hitch()は引数により2種類の使い方がある。

1つ目の引数としてオブジェクト、2つ目の引数としてメソッド名を文字列で指定すると、指定したオブジェクトのメソッドのfunctionを返す。例えば、var func = dojo.lang.hitch(foo, "bar")を実行するとfoo.bar()を返す。

dojo.declare('my.classes.foo', null, {
initializer: function(arg) {
this.id = 'foo';
},
getId: function() {
return "I am a foo";
},
method: function() {
return "A method in foo";
}
});

var obj = new my.classes.foo();
var func = dojo.lang.hitch(obj, 'getId');
func();
--> "I am a foo"

dojo.lang.hitch()に対して、1つ目の引数としてscope、2つ目の引数としてfunctionを指定することで、scopeを指定してfunctionを実行できる。

dojo.lang.hitch(this, func); 

dojo.lang.has()は、連想配列/オブジェクトの添え字/プロパティの名前の中に指定した名前が含まれるかどうかを返す。以下の例ではtrueを返す。

dojo.lang.has( { a: "A", b: "B" }, "b" );

2007年3月13日 (火)

イベント割り当て

Fromなどのオブジェクトにイベント時の動作を割り当てることができる。例えば、以下のDojo widgetに対して、onClickを割り当てるときは、

<button dojoType="Button" widgetId="helloButton">Press Me</button>

以下のように、dojo.event.connectを用いる。1つ目の引数としてオブジェクト、2つ目にイベント、3つ目が割り当てる関数を指定する。これより、ボタンが押されたら、helloPressedが呼び出される。

function helloPressed(){
  dojo.debug('Hello World!');
}
var helloButton = dojo.widget.byId('helloButton');
dojo.event.connect(helloButton, 'onClick', 'helloPressed');

Dojoのwidgetだけでなく、通常のFormオブジェクトに対しても割り当てることができる。例えば、以下のボタンに対して、

<input type="button" id="testbutton" value="ボタン">

以下のように同じdojo.event.connectを用いてイベントを割り当てられる。なぜか、Dojo 0.4.1では、'onclick'のようにcがこのときは小文字となるので注意すること。

var testButton = dojo.byId("testbutton");
dojo.event.connect(testButton, 'onclick', 'helloPressed');

o.helloPressed()のように、オブジェクトのメソッドを呼び出したいときは、3つ目の引数でオブジェクト、4つ目の引数でメソッド名を指定する。

var testButton = dojo.byId("testbutton");
dojo.event.connect(testButton, 'onclick', o, 'helloPressed');
呼び出される関数は、引数としてイベントオブジェクトを取得することもできる。
function helloPressed(event){
  dojo.debug(event.pageY);
}

var helloButton = dojo.widget.byId('helloButton');
dojo.event.connect(helloButton, 'onClick', 'helloPressed');

dojo.event.connet()は、HTMLの読み込みが完了してから実行されるように、HTMLのbodyのonload属性で呼び出した関数内に記述するのがよいようです。Dojoでは、dojo.addOnLoad()でonloadで呼ばれる関数を指定することもできる。

ここでは、1つのオブジェクトに1つのイベントだけを割り当てているが、1つのオブジェクトに対してdojo.event.connect()を複数記述して、複数のイベントを割り当てることも出来る。このとき、dojo.event.connect()で指定した順番に呼ばれる。

dojo.event.disconnect()により、割り当てたイベントを削除することもできる。dojo.event.disconnect()の引数はdojo.event.connect()と同じものを指定する。

Dojoインストール

Dojoは http://dojotoolkit.org/ からダウンロードできます。dojo-xxx-ajax.zip をダウンロードして解凍したら、dojo.js, iframe_history.html, srcディレクトリを、Dojoを利用する場所にまとめて置きます。

Dojoのコードは以下の順番で記述します。dojo.jsのロードのみが必須で、その他は必要に応じてこの順番で記述します。HTMLのロードが終わってからでなければ、dojo.widget.byId("helloButton")などのHTMLオブジェクトを参照できないので、この順番を守ることが重要となります。

  1. djCofigの設定
  2. dojo.jsのロード
  3. dojo.requireの実行
  4. 初期化関数の定義
  5. addOnLoadによる初期化関数の呼び出し

以下に簡単な例を示します。

<html>
<head>
   <script type='text/javascript'>
    var djConfig = { isDebug: true };
   </script>

   <script src='dojo.js' type='text/javascript'>

   <script type="text/javascript">
            dojo.require("dojo.widget.Button");

            function helloPressed(){
              dojo.debug('Hello World!');
            }

            function init(){
              var helloButton = dojo.widget.byId('helloButton');
              dojo.event.connect(helloButton, 'onClick', 'helloPressed');
            }

            dojo.addOnLoad(init);
        </script>
</head>
<body>
  <button dojotype="Button" widgetid="helloButton">Press Me</button>
</body>
</html>

1. djCofigの設定

最初にdjConfigによりDojoの設定をします。djConfigで設定できる値を以下に示します。「:」の後は、デフォルト値です。

  • isDebug: false
  • allowQueryConfig: false
  • baseScriptUri: ""
  • baseRelativePath: ""
  • libraryScriptUri: ""
  • iePreventClobber: false
  • ieClobberMinimal: true
  • locale: undefined
  • extraLocale: undefined
  • preventBackButtonFix: true
  • searchIds: []
  • parseWidgets: true 

 

2. dojo.jsのロード

Dojoを利用するHTMLでは、下記のようにsrcriptタグでdojo.jsを読み込みます。

<script type="text/javascript" src="dojo.js" />

Dojo 0.4.2から、クロスドメインに対応した。これにより、Dojoのライブラリを自分で配置せずに、AOLのCDNで配信しているDojoのライブラリを直接参照して利用できる。AOLのCDNを直接参照するときは、以下のように記述する。 Editor Widgetなど一部の機能では、HTMLファイルをローカルサーバに置く必要がある。

<script type="text/javascript" src="http://o.aolcdn.com/dojo/0.4.3/dojo.js"></script>

3. dojo.requireの実行

srcディレクトリに含まれるその他のDojoのファイルは細分化されており、必要なリソースのみをロードするようになっています。

dojo.require()を用いて利用するwidgetなどのDojoのリソースを呼び出します。例えば回のように記述します。

dojo.require("dojo.lfx.html");
dojo.require("dojo.lfx.extras");

下記のようにワイルドカード(*)を用いてリソースを指定することもできます。

dojo.require("dojo.lfx.*");

Dojoのrequireで指定する名前空間の名前は、各リソースファイル(.js)のディレクトリ構成にそのまま対応します。

例えば、dojo.requre("dojo.i18n.number");によりロードされる、リソースファイルは、dojo\src\i18n\number.jsです。

dojo.requireIf(condition, "package")を使うと、conditionがtrueのときだけpackageをロードします。

4. 初期化関数の定義

次のaddOnLoadで呼ばれる初期化関数を定義します。先の例では、init()が初期化関数になります。

5. addOnLoadによる初期化関数の呼び出し

dojo.addOnLoad()で、HTMLページが読み込まれた後に呼び出される関数を指定します。関数を直接指定する方法と、下記のように、オブジェクトとそのメソッド名を指定する方法があります。dojo.addOnLoadはHTML bodyタグのonLoad属性に関数を書く場合や、window.onLoadと同じ動作をする。しかし、Dojoでは、windows.onLoadを上書きしているので、dojo.addOnLoadで呼び出す必要がある。

dojo.addOnLoad(object, "functionName")

HTMLのロードが終わらないとWidgetオブジェクトがインスタンス化されないため、DojoのWidgetオブジェクトを取得するときは、HTMLのロードが終わってから実行する必要がある。dojo.addOnLoadで呼び出した関数内であれば、確実にHTMLのロードが終わってから呼ばれる。

dojo.addOnLoadと同じ引数を取るdojo.addOnUnloadはページがアンロードされたとき、リロードされたときやページが移ったときなどに呼ばれる関数を指定する。

2007年3月11日 (日)

Dojo 0.4.2のまとめ

Dojo 0.4.2について少しずつ書いていきます。ここはまとめページ。

Dojo http://dojotoolkit.org/ は、The Dojo Foundationにより提供されているオープンソースのJavaScriptツールキットである。

Dojoは、Ajax呼び出しから、イベント処理、タブやツリーなどの各種GUI部品など、広範な機能を提供しており、機能ごとにファイルが分かれていて必要な機能だけを動的にロードする仕組みとなっているのが特徴となっている。 ブラウザは、Safari 2.0.x, Opera 9.0+, IE(Windows) 6.0+, Firefox 1.0+/Mozilla, Konqueror 3.5+に対応している。

概要

オブジェクト

文字列

XML

基本機能

Ajax機能

デザイン

フォーム部品

レイアウト

その他のGUI部品

その他

書籍

デバッグ

DojoのデバッグAPIを用いるには、dojo.jsを読み込む前にdjConfigのパラメータisDebugをtrueに設定する。

var djConfig = {isDebug: true};

指定しなければデバッグ情報は最後に表示される。デバッグ情報の表示先を指定したいときは、表示する場所でid="dojoDebug"を指定する。例えば、<div id="dojoDebug"></div>のように記述する。

指定するidの値を "dojoDebug"から変更したいときは、下記のようにdjConfig.debugContainerIdの値を指定する。この例では、<div id="test"></div>となる。

var djConfig = {
  isDebug: true,
  debugContainerId : 'test'
};

デバッグ表示したいときは、下記のAPIを用いる。

  • dojo.debug(message);
    • 引数のメッセージを表示する
  • dojo.debugShallow(object);
    • 引数のオブジェクトの全てのメンバー(メソッドとパラメータ)を表示する
  • dojo.debugDeep(object);
    • 新しくウィンドウを開いて、引数のオブジェクトのtree構造を表示する

« 2007年2月 | トップページ | 2007年4月 »