各ガジェットのパッケージングについて

各ガジェットプラットフォーム向けにガジェットを作成したら
パッケージングして配布できるようにします。
ではそのファイルフォーマットというと
拡張子はそれぞれ異なりますが
大体がzip圧縮されたファイルとなっています。

なので作ったガジェットはAntなどを使って
zip圧縮して指定された拡張子を付けてあげます。
どうなっているかというと。
 Windows サイドバーガジェット:
  拡張子”gadget”でのzip圧縮

 Opera ウィジェット:
  拡張子”wgt”でのzip圧縮

 Mac OS X Dashboard ウィジェット
  拡張子”zip”でのzip圧縮

 Adobe AIR
  拡張子”air”でのzip圧縮 (Adobe AIR SDKのadtコマンドを使用)

 iGoogle ガジェット
  そのままサイトにアップロード

 Google デスクトップ ガジェット
  拡張子”gg”でのzip圧縮

 Yahoo!ウィジェット
  拡張子”widget”での独自のフラットファイル形式 (Converter.exeを使用)

Opera ウィジェット エミュレータ

OperaはPCでのブラウザのシェアとしては大きくないんだけれども
Wiiなどのゲーム機やモバイル機、携帯などにも
搭載されているのでそれを合わせると結構な数になると思います。
当然Opera ウィジェットもWiiで動いたりします。
そこでの動作環境の確認用にエミュレータがあります。
Opera ウィジェットとしてOperaから提供されています。

エミュレータで動かすためには
下記の文章を書いてあげる必要があります。
 <script type=”text/javascript” language=”javascript”>
  if(parent.emulator){
   parent.emulator.begin(window);
  }
 </script>

注意点はあくまで動かしている
Operaのバージョン上でエミュレートしており
実機のOepraバージョンとは異なったりします。
残念ながらやっぱりエミュレータでしかないところです。

Opera ウィジェットでのローカライズについて

Opera ウィジェットでのローカライズについてですが
Opera ウィジェットではないです。
Opera ウィジェットの方ではなにもしてくれません。
なので自前で行うしかないです。

どうやって自前で行うかというと
jsファイルを言語ごとに分けておいて
表示したい言語によってそれを切り分けます。
対象となるエレメントを取得して削除しちゃいます。
そして読込みたいエレメントを追加します。

こんな風にsetLocalizedを呼んで言語ファイルを変更して
getStringを呼んでローカライズメッセージを取得します。
下記のような形で。

 this.LANG_NAME     = localizedStrings;
 this.LANG_NAME_JS  = this.LANG_NAME + “.js”;
 this.ROOT_LOCATION = location.toString().substring(0, location.toString().lastIndexOf(“/”)) + “/”;

 /**
  * ローカライズの設定。
  *
  * @param <string> lang 言語名
  */
 function setLocalized(lang) {
  if (lang == null) {
   throw new Error(“lang is null”);
  }
  if (this.gadget.isAIR()) {
   return;
  }

  var jsObjList = document.getElementsByTagName(“script”);
  for (var cnt = 0; cnt < jsObjList.length; cnt++) {
   var jsSrc = jsObjList[cnt].src;
   if (jsSrc.lastIndexOf(this.LANG_NAME_JS) < 0) {
    continue;
   }

   var jsSrc = null;
   if (lang == “ja”) {
    jsSrc = this.LANG_NAME_JS;
   } else {
    jsSrc = lang + “/” + this.LANG_NAME_JS;
   }

   if (
    jsObjList[cnt].src == jsSrc
    || jsObjList[cnt].src == this.ROOT_LOCATION + jsSrc
   ) {
    break;
   }

   // 今のjsを削除
   var headObj = jsObjList[cnt].parentNode;
   headObj.removeChild(jsObjList[cnt]);

   // 新しいjsを追加
   var jsObj = document.createElement(“script”);
   jsObj.src    = jsSrc;
   jsObj.onload = initSettingData;
   headObj.appendChild(jsObj);
   break;
  } // for (var cnt = 0; cnt < jsObjList.length; cnt++)
 }

 /**
  * ローカライズされた文字列の取得。
  *
  * @param  <string> キー
  * @return <string> ローカライズされた文字列
  */
 function getString(key) {
  if (key == null) {
   throw new Error(“key is null”);
  }

  var ret = null;
  try {
   ret = localizedStrings[key];

  } catch(ex) {
  }

  if (ret == null || ret === undefined) {
   ret = key;
  }

  return ret;
 }

設定ファイルへの読み書込み

今回は各種ガジェットでの設定ファイルへの読み書込みについてです。
キーに対して値の書込みを行い、キーを指定して値の読込みを行います。
なのでいっぱいキーを作っても面倒なので
値をJSONにしておくと便利です。
そしてOpera ウィジェット、Mac OS X Dashboard ウィジェットでは
書き込みを行う際に通常、キーと値なところが
値、キーの順番で設定しますのでちょっと紛らわしいです。

こんな感じで行います。
 Windows サイドバーガジェット:
  value = System.Gadget.Settings.readString(key);

  System.Gadget.Settings.writeString(key, value);

 Opera ウィジェット:
  value = widget.preferenceForKey(key);

  widget.setPreferenceForKey(value, key);

 Mac OS X Dashboard ウィジェット:
  value = widget.preferenceForKey(key);

  widget.setPreferenceForKey(value, key);

 Adobe AIR:
  var dir  = air.File.applicationStorageDirectory;
  var file = dir.resolvePath(key);
  if (file.exists) {
   var fileStream = new air.FileStream();
   fileStream.open(file, air.FileMode.READ);
   value = fileStream.readUTFBytes(fileStream.bytesAvailable);
   fileStream.close();
  }

  var dir        = air.File.applicationStorageDirectory;
  var file       = dir.resolvePath(key);
  var fileStream = new air.FileStream();
  fileStream.open(file, air.FileMode.WRITE);
  fileStream.writeUTFBytes(value);
  fileStream.close();

 iGoogle ガジェット:
  var pref = new _IG_Prefs(__MODULE_ID__); // new gadgets.Prefs();
  value = pref.getString(key);

  pref.set(key, value);

 Google デスクトップ ガジェット:
  value  = options.getValue(key);

  options.putValue(key, value);

 Yahoo!ウィジェット:
  value = preferences.key.value;

  preferences.key.value = value;

ガジェットでのAjaxセキュリティ

ガジェットからのAjax使っての外部通信ですが
ローカルからのブラウザアクセスと同様に結構バラバラです。
基本はマニフェストファイルに接続先ドメインを記述します。

まあ、下記のようになっています。
 Windows サイドバーガジェット: (特になし、今後かかりそう)

 Opera ウィジェット: 下記のようにconfig.xmlに接続先ドメインを記述
  <security>
   <access>
    <protocol>http</protocol>
    <port>80</port>
    <host>www.aaoh.co.jp</host>
    <host>aaoh.co.jp</host>
   </access>
  </security>

 Mac OS X Dashboard ウィジェット: 下記のように Info.plistに
  外部通信を許可することを記述
  <key>AllowNetworkAccess</key>
  <true />

 Adobe AIR: (特になし)

 iGoogle ガジェット: _IG_FetchXmlContentメソッドを使用すれば問題なし

 Google デスクトップ ガジェット: (特になし)

 Yahoo!ウィジェット: 下記のようにIwidget.xmlにに接続先ドメインを記述
  <security>
   <http name=”aaoh_co_jp”>www.aaoh.co.jp</http>
  </security>

Silverlightはちょっと特殊で通信を行うサーバー側に
このクライアントと通信してもよいという
マニフェストファイルを置きます。
こんな感じで。
 <cross-domain-policy>

  <!– すべてのクライアントからのアクセスを許可する –>
  <allow-http-request-headers-from
   domain=”*”
   headers=”*”
  />
 </cross-domain-policy>

リンクをブラウザで開く

ガジェット作成していてリンクをクリックしたら
ブラウザでそのURLを開きたいとき。
Mac OS X Dashboard ウィジェット、Adobe AIRだけは
拡張APIを呼んであげなければいけません。
JavaScriptからブラウザを開きたいときにはわかるんだけれども
“aタグ”で記述しているんだからそれを解釈してよと思います。

ちなみにリンクをブラウザで開く拡張APIは下記となっております。
 Windows サイドバーガジェット: <aタグ> または System.Shell.execute(url);

 Opera ウィジェット: <aタグ> または window.open(url);

 Mac OS X Dashboard ウィジェット: widget.openURL(url);

 Adobe AIR: air.navigateToURL(new air.URLRequest(url));

 iGoogle ガジェット: <aタグ> または window.open(url);

 Google デスクトップ ガジェット: <aタグ> またはframework.openUrl(url);

 Yahoo!ウィジェット: openURL(url);