GAE や Google Closure Library などの話題を扱います。python 初心者です。

2010年1月29日金曜日

Closure Library - ポップアップメニュー

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
goog.ui.PopupMenu と goo.ui.MenuButton を試した。

PopupMenu は名前のまんまのメニュー。ボタンや特定のエリアにくっつけて使う。
上記はボタンにくっつけた例。
作成方法は先日紹介したボタンと同様に2通りある。
(1) Popup インスタンスを作成する方法
(2) 特定の DIV を装飾(decorate)する方法

(2)の方法を使った場合はこんな感じ。
<h2>(1) Decorated Popup</h2>
    <button id="button1">Popup</button>

    <div id="menu1" for="button1" class="goog-menu" style="display:none">
      <div class="goog-menuitem">monkey</div>
      <div class="goog-menuitem">dog</div>
        <div class="goog-menuseparator"></div>
      <div class="goog-menuitem">cat</div>
        <div class="goog-menuseparator"></div>
      <div class="goog-menuitem">dolphin</div>
    </div>

    <script>
      var pm1 = new goog.ui.PopupMenu();
      pm1.setToggleMode(true);
      pm1.decorate(goog.dom.$('menu1'));

      goog.events.listen(pm1, goog.ui.Component.EventType.ACTION,
        function(e) {
          alert(e.target.getCaption());
        });
    </script>

ボタンと PopupMenuを作り紐づける。ボタン以外の何でも紐付けすることができる。



次に MenuButton。こちらはボタンと PopupMenu を組み合わせたもの。GMailで使われているあのスタイル。

コードはこんな感じ。
<h2>(2) Decorated MenuButton</h2>
    <div id="button2" class="goog-menu-button" title="MenuButton">
      <span style="vertical-align:middle">Format</span>
      <div id="menu2" class="goog-menu">
        <div class="goog-menuitem">monkey</div>
        <div class="goog-menuitem">dog</div>
        <div class="goog-menuseparator"></div>
        <div class="goog-menuitem">cat</div>
        <div class="goog-menuseparator"></div>
        <div class="goog-menuitem">dolphin</div>
      </div>
    </div>

    <script>
      var btn2 = goog.ui.decorate(goog.dom.$('button2'));
      goog.events.listen(btn2, goog.ui.Component.EventType.ACTION,
        function(e) {
          alert(e.target.getCaption());
        });
    </script>

こちらはボタンの中に PopupMenuが入った感じだ。ボタンとPopupMenuを組み合わせる場合はこちらの方が簡単に書ける。

デモはこちら:
http://closuresample.appspot.com/html/popup.html

2010年1月23日土曜日

Closure Library を Closure Compiler でコンパイル

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
JavaScriptファイルの圧縮
下記が非常に参考になった。
Closure Library で作る簡易ドローツール(Python Hack-a-thon #3 資料) - WebOS Goodies

まだまだ日本語情報が少ない中、Closure Tools に関する貴重な情報がたくさん載っている。

このページの中の「JavaScriptファイルの圧縮」を参考にして、Closure Library を使った簡単な JavaScriptをコンパイルしてみる。

レシピ
まず HTMLファイル:html/button-min.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
    <script src="/js/button.js"></script>
    <link rel="stylesheet" href="/css/dialog.css">
    <link rel="stylesheet" href="/css/button.css">
  </head>
  <body>
    <h1>Closure Libraray: button sample</h1>
    <hr/>

    <h2>(1) goog.ui.Button</h2>
    <div id="button1"></div>

    <h2>(2) goog.ui.decorate</h2>
    <div id="button2" class="goog-custom-button">
      <span style="color: blue">BUTTON-<b>2</b></span>
    </div>

    <div id="button3" class="goog-custom-button">
      <span style="font-size: 7pt">BUTTON-<b>3</b></span>

    </div>

  <script>
    setupButtons();
  </script>

  </body>
</html>

goog.ui.CustomButton や decorate を使っている。Closure Library はとりあえず googleのサイトを参照している(コンパイル後に取り除く予定)。

JavaScriptファイル:js/button.js
goog.require('goog.ui.CustomButton');
goog.require('goog.ui.decorate');

function setupButtons() {
        var btn1 = new goog.ui.CustomButton('BUTTON-1');
        btn1.render(goog.dom.$('button1'));
        goog.events.listen(btn1, goog.ui.Component.EventType.ACTION,
            function(e) {
                var target = e.target;
                alert('button1: ' + target);
            }); 

        var btn2 = goog.ui.decorate(goog.dom.$('button2'));
        goog.events.listen(btn2, goog.ui.Component.EventType.ACTION,
            function(e) {
                var target = e.target;
                alert('button2: ' + target);
            }); 
        var btn3 = goog.ui.decorate(goog.dom.$('button3'));
}

ボタンの定義を行っている。button-min.html の最後で setupButtons()が呼び出される。

実行するとこんな画面が出る。

コンパイル
やってみよう。

closure ライブラリは ~/Development/closure-tools/closure に、
closuer compiler は ~/Development/closure-tools/compiler にあるとする。

python ~/Development/closure-tools/closure/bin/calcdeps.py \
            -i button.js \
            -p ~/Development/closure-tools/closure \
            -o compiled \
            -c ~/Development/lib/closure-tools/compiler/compiler.jar \
            -f "--comilation_level=ADVANCED_OPTIMIZATIONS" > button-min.js
calcdeps.py: Scanning files...
calcdeps.py: Finding Closure dependencies...
calcdeps.py: Compiling with the following command: java -jar /Users/hashi/Development/lib/closure-tools/compiler/compiler.jar --js /Users/hashi/Development/closure-tools/closure/go
   :
   :
.js --js /Users/hashi/Development/closure-tools/closure/goog/ui/custombutton.js --js button.js --compilation_level=ADVANCED_OPTIMIZATIONS
$

数分後に button-min.js が生成された(PowerPCは今となっては非力でとても重い..)。
$ ls -l 
total 48
-rw-r--r--  1 hashi  hashi  19163  1 22 21:35 button-min.js
-rw-r--r--  1 hashi  hashi    593  1 22 21:18 button.js

サイズが大きくなっているのは Closure Library を取り込んでいるため。

中身はこんな感じ。


これで元の JavaScriptを差し替えてみよう。

新バージョン
button-min.html を書き換える。
書き換え前:
  6     <script src="http://closure-library.googlecode.com/svn/trunk/closure/goo    g/base.js"></script>
  7     <script src="/js/button.js"></script>
これを下のようにする。
書き換え後:
  6     <script src="/js/button-min.js"></script>

動かしてみよう。

ボタンがうまく表示されていない。問題があるようだ。
Safariのエラーログを見ると setupButtons()が見つけられないとのこと。



ドキュメントを見ると ADVANCED_OPTIMIZATIONS を付けた場合、呼び出しの無い関数は削除されてしまうとのこと。
Advanced Compilation and Externs - Closure Compiler - Google Code

setupButtons()の呼び出しは HTML内だけに記述してあって button.js には定義だけしか書いていない。コンパイラは button.js だけしか見ていないので使われていない関数と判断したようだ。

オプションから ADVANCED_OPTIMIZATIONS を外して再度コンパイルしてみる。
python ~/Development/closure-tools/closure/bin/calcdeps.py \
            -i button.js \
            -p ~/Development/closure-tools/closure \
            -o compiled \
            -c ~/Development/closure-tools/compiler/compiler.jar \
            > button-min.js

$ ls -l
-rw-r--r--  1 hashi  hashi  133677  1 22 22:12 button-min.js
-rw-r--r--  1 hashi  hashi     593  1 22 21:18 button.js
サイズはずいぶん大きくなった。さっきのが 19,163バイトだったので約7倍。

さて実行しなおしてみよう。

出た。

比較
コンパイル前とコンパイル後でどれだけ違うか比べてみた。サンプルは GAEにデプロイしてある。

コンパイル前
http://closuresample.appspot.com/html/button.html

コンパイル後
http://closuresample.appspot.com/html/button-min.html


結果はこの通り。※Safariの Webインスペクタで計測

コンパイル前

コンパイル後


JavaScriptの読み込み時間が8割近く短縮された。全体でも約1/3に短縮。体感速度も全然速い。

- - - -
Closure Compiler は使えそうだ。ただし開発中は未コンパイル状態なのでやっぱり遅いまま。開発効率にかかわるのでどうにか改善したいところだが。

2010年1月22日金曜日

Mac OS X v10.5 (PowerPC) で Closure Compiler を使う(までの長い道のり)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
例外発生
Closure Compiler を試すべく compiler.jar をダウンロードして実行するも例外発生。
$ java -jar compiler.jar --help
Exception in thread "main" java.lang.UnsupportedClassVersionError: Bad version number in .class file
     at java.lang.ClassLoader.defineClass1(Native Method)
     at java.lang.ClassLoader.defineClass(ClassLoader.java:676)
     at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
     at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
     at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
     at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
     at java.security.AccessController.doPrivileged(Native Method)
     at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:317)
     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:280)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
     at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:375)
調べると、どうも Closure Compiler は Java1.6以上で動作するらしい。自分のノート (Mac OS X v10.5 / PowerPC)のバージョンを調べると Java1.5だった。
$ java -version
java version "1.5.0_22"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_22-b03-333-9M3125)
Java HotSpot(TM) Client VM (build 1.5.0_22-147, mixed mode, sharing)

Java1.6
Mac OS X 10.5 でも Java1.6が提供されているっぽい。
About the security content of Java for Mac OS X 10.5 Update 6

実際 Library内を見ると 1.6 というのが見つかった。
$ ls -l /System/Library/Frameworks/JavaVM.framework/Versions/
total 56
lrwxr-xr-x  1 root  wheel    5 12 18 09:10 1.3 -> 1.3.1
drwxr-xr-x  3 root  wheel  102  9 29  2007 1.3.1
lrwxr-xr-x  1 root  wheel    5  9 17 17:25 1.4 -> 1.4.2
lrwxr-xr-x  1 root  wheel    3 10 27  2007 1.4.1 -> 1.4
drwxr-xr-x  8 root  wheel  272 11 19  2006 1.4.2
lrwxr-xr-x  1 root  wheel    5 12 18 09:10 1.5 -> 1.5.0
drwxr-xr-x  8 root  wheel  272 11 19  2006 1.5.0
lrwxr-xr-x  1 root  wheel    5 12 18 09:10 1.6 -> 1.6.0
drwxr-xr-x  8 root  wheel  272 10  2  2008 1.6.0
drwxr-xr-x  9 root  wheel  306 12 18 09:11 A
lrwxr-xr-x  1 root  wheel    1 12 18 09:11 Current -> A
lrwxr-xr-x  1 root  wheel    3 12 18 09:10 CurrentJDK -> 1.5
JDKの差し替え方法の情報も見つかった。
Gridshore » Java 6 for Mac OSX leopard

少し調べてみる。

まずJAVA_HOME を見てみる。
echo $JAVA_HOME
/System/Library/Frameworks/JavaVM.framework/Home
この Homeはどこにリンクしているのか。
ls -l $JAVA_HOME
lrwxr-xr-x  1 root  wheel  24 12 18 09:10 /System/Library/Frameworks/JavaVM.framework/Home -> Versions/CurrentJDK/Home
CurrentJDK はどこにリンクしているのか。
$ ls -l /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK
lrwxr-xr-x  1 root  wheel  3 12 18 09:10 /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK -> 1.5
つまり $JAVA_HOME は
/System/Library/Frameworks/JavaVM.framework/Versions/1.5 にリンクしている。

一方 javaコマンドはどうか。
$ which java
/usr/bin/java
$ ls -l /usr/bin/java
lrwxr-xr-x  1 root  wheel  74 12 18 09:10 /usr/bin/java -> /System/Library/Frameworks/JavaVM.framework/Versions/Current/Commands/java
Current はどこへリンクしているのか。
$ ls -l  /System/Library/Frameworks/JavaVM.framework/Versions/Current
lrwxr-xr-x  1 root  wheel  1 12 18 09:11 /System/Library/Frameworks/JavaVM.framework/Versions/Current -> A
なるほど。Current と CurrentJDK を差し替えれば 1.6 になりそうだ。
やってみよう。
$ cd /System/Library/Frameworks/JavaVM.framework/Versions/
$ sudo rm CurrentJDK
$ sudo ln -s 1.6 CurrentJDK
java コマンドの A は何に差し替えればいいのだろうか。わからずとりあえず java実行。
$ java
Unable to launch "/System/Library/Frameworks/JavaVM.framework/Home/bin/java" (86)
だめだな。

Java Preferences.app
いろいろ探していると
アプリケーション > ユーティリティ> Java Preferences.app
なるものを見つけた。ここで Javaのバージョンが切り替えられるらしい。

が、ここに出てくるのは 1.5 と 1.4.2 だけ。

うーむ。どういうことだ。

Apple Supports..
さらに調べると PowerPCでは Java 1.6が使えないことが判明。
OS XでJava 6が利用可能に:PPCと32-bit Intelは切り捨て - builder by ZDNet Japan

Appleによる公式サポート対象は Intel64bitのみ。
おー。なんてこった。

上記ページでは SoyLatte という FreeBSDから移植された Java6実装が紹介されていた。こっちを見てみよう。

SoyLatte
SoyLatte - Port of BSD Java

このページの PowerPC 向け(Java7)ダウンロードする。
32-bit OpenJDK 7 Beta 1 for Mac OS X 10.5 PowerPC (Beta Release): openjdk7-macppc-2009-12-16-b4.tar.bz2 (sig)
一気にバージョンが 7 になっているがまあ大丈夫だろう。

tar コマンドで解凍する。
$ tar xvfj openjdk7-macppc-2009-12-16-b4.tar.bz2
  :
  :
できたフォルダを適当なところへ移動しておく。ここでは /opt/local/openjdk を作成してその中へ入れておいた(先に移動してから解凍すれば良かった)。
$ sudo mkdir /opt/local/openjdk
$ sudo mv openjdk7-macppc-2009-12-16-b4 /opt/local/openjdk/
てっとりばやく javaコマンドを試してみる。
$ cd /opt/local/openjdk/openjdk7-macppc-2009-12-16-b4/jre/bin
$ ./java -version
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-landonf_2009_12_16_12_54-b00)
OpenJDK Zero VM (build 17.0-b05, interpreted mode)
$
おー、動いた?

とりあえず javaコマンドが使えればいいので bashのエイリアスを切っておこう。
$ alias java="/opt/local/openjdk/openjdk7-macppc-2009-12-16-b4/jre/bin/java"
※ ~/.bash_profile などに書いておくと良い。

いよいよ Closure Compiler を動かしてみよう。

Compile JavaScript
$ java -jar compiler.jar --help
Usage: java [jvm-flags...] com.google.javascript.jscomp.CompilerRunner [flags...] [args...]
where flags are
 Standard flags:
   --help describes all flags
   --helpshort describes the main class' flags
   --helpxml emits XML description of all flags
  :
  :
出た。やった。

試しに hello.js をコンパイルしてみる。
$ cat hello.js
// A simple function.
function hello(longName) {
 alert('Hello, ' + longName);
}
hello('New User');
$ java -jar compiler.jar --js hello.js --js_output_file hello-compiled.js
  :
(待つ事 1分弱)
$
$ ls *.js
hello-compiled.js hello.js
中身は?
$ cat hello-compiled.js 
function hello(a){alert("Hello, "+a)}hello("New User");
出来た。ちょっとうれしい。
(ただ PowerPC で Javaを動かすのはチト重い)

2010年1月20日水曜日

GAE で closure library を使う

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
当初ローカルにあった closureフォルダ一式を GAEへ上げていたが、デプロイで時間がかかるし無駄が多い。

そこで(勝手に)googleに置いてあるライブラリを参照させてもらった。

<script src="http://closure-
 library.googlecode.com/svn/trunk/closure/goog/base.js"></script>

css はカスタマイズするので最低限のみ自前でホストする。
goog/demos/css/ 内で使うものだけ持ってきてある。

[closuresample]$ ls css
button.css common.css dialog.css
[closuresample]$ 

Closure Library - ボタン

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ボタンを試してみた。

Button (Closure Library API Documentation - JavaScript)




デモ:
http://closuresample.appspot.com/html/button.html

ボタンの作り方には2種類ある。

一つは goog.ui.Button のオブジェクトを生成する方法。(1)がこれにあたる。
<h2>(1) goog.ui.Button</h2>
    <div id="button1"></div>
    <script>
      var btn1 = new goog.ui.CustomButton('BUTTON-1');
      btn1.render(goog.dom.$('button1'));
      goog.events.listen(btn1, goog.ui.Component.EventType.ACTION,
        function(e) {
          var target = e.target;
          alert('button1: ' + target);
        });
    </script>

もう一つはあらかじめ用意した <div> をボタン化する方法。(2)がこれにあたる。面白い。
<h2>(2) goog.ui.decorate</h2>
<div id="button2" class="goog-custom-button">
      <span style="color: blue">BUTTON-<b>2</b></span>
    </div>

    <div id="button3" class="goog-custom-button">
      <span style="font-size: 7pt">BUTTON-<b>3</b></span>

    </div>
    <script>
      var btn2 = goog.ui.decorate(goog.dom.$('button2'));
      goog.events.listen(btn2, goog.ui.Component.EventType.ACTION,
        function(e) {
          var target = e.target;
          alert('button2: ' + target);
        });
      var btn3 = goog.ui.decorate(goog.dom.$('button3'));
    </script>

こっちだと装飾がしやすい。どちらも生成したオブジェクトはイベントハンドリングを追加したりして好きにできる。

2010年1月16日土曜日

サーバ(GAE)へデプロイする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
デプロイするためには先に GAE(Google app engine)へログインしてアプリケーションを作成しておく。




この時 Application Identifier をローカルで作ったアプリ名と合わせておく。

GAE上で作成ができたら GoogleAppEngineLauncher を使ってデプロイする。アプリを選んで "Deploy" ボタンを押すだけ。たったこれだけでデプロイができる。


なお前回シンボリックリンクで作成した Closure Library のディレクトリは今回実体としてアプリディレクトリ内に配置しておいた。

ログ出力:
*** Running appfg.py with the following flags:
    --no_cookies --email=xcatsan@mac.com --passin update
Application: closuresample; version: 1.
Server: appengine.google.com.
Scanning files on local disk.
Scanned 500 files.
Scanned 1000 files.
Scanned 1500 files.
Scanned 2000 files.
Scanned 2500 files.
Scanned 3000 files.
Scanned 3500 files.
Scanned 4000 files.
Scanned 4500 files.
Scanned 5000 files.
Scanned 5500 files.
Scanned 6000 files.
Scanned 6500 files.
Scanned 7000 files.
Scanned 7500 files.
Scanned 8000 files.
Scanned 8500 files.
Initiating update.
Password for xcatsan@mac.com: Cloning 2855 static files.
Cloned 100 files.
Cloned 200 files.
Cloned 300 files.
Cloned 400 files.
Cloned 500 files.
Cloned 600 files.
Cloned 700 files.
Cloned 800 files.
Cloned 900 files.
Cloned 1000 files.
Cloned 1100 files.
Cloned 1200 files.
Cloned 1300 files.
Cloned 1400 files.
Cloned 1500 files.
Cloned 1600 files.
Cloned 1700 files.
Cloned 1800 files.
Cloned 1900 files.
Cloned 2000 files.
Cloned 2100 files.
Cloned 2200 files.
Cloned 2300 files.
Cloned 2400 files.
Cloned 2500 files.
Cloned 2600 files.
Cloned 2700 files.
Cloned 2800 files.
Cloning 2 application files.
Uploading 1082 files and blobs.
Processed 500 out of 1082.
Processed 1000 out of 1082.
Uploaded 1082 files and blobs
Deploying new version.
Checking if new version is ready to serve.
Will check again in 1 seconds.
Checking if new version is ready to serve.
Will check again in 2 seconds.
Checking if new version is ready to serve.
Closing update: new version is ready to start serving.
Uploading index definitions.
If deploy fails you might need to 'rollback' manually.
The "Make Symlinks..." menu option can help with command-line work.
*** appcfg.py has finished with exit code 0 ***

デプロイ直後からアプリへアクセスできる。
実際に稼働中のURL↓
http://closuresample.appspot.com/



GAEでは Webベースの管理画面が用意されていて、アクセス統計やバッチ(Cron Jobs)管理、キュー管理、データ(DB)管理、などなどさまざまなことが行えるようになっている。



なおGAEでアプリ作成せずにローカルのアプリをデプロイするとエラーとなる。
:
  :
Scanned 8500 files.
Initiating update.
Password for xcatsan@mac.com: Error 403: --- begin server output ---
You do not have permission to modify this app (app_id=u'closuresample').
--- end server output ---
If deploy fails you might need to 'rollback' manually.
The "Make Symlinks..." menu option can help with command-line work.
*** appcfg.py has finished with exit code 1 ***

2010年1月15日金曜日

Google Closure Library を GAEで使う

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Google Closure Library は Google製のJavaScriptライブラリ(フレームワーク)。

Closure Library - Google Code


Googleのアプリケーションでも使われているライブラリらしい。

UIコンポーネントも用意されている。


ダイアログとかは確かにどこかでみたデザイン。



特徴
  • Google謹製
  • よくテストされたコード(自称)
  • UI コンポーネント
  • DOM操作
  • サーバとの通信
  • アニメーション
  • データ構造
  • ユニットテスト
  • リッチテキストエディタ
  • 複数のブラウザ互換
  • などなど

ライセンスはソースコードを見ると Apache License, Version 2.0 となっていた。


APIドキュメント(英語)
Closure Library API Documentation (Closure Library API Documentation - JavaScript)

APIドキュメントは非常によく整備されている。ドキュメントが整備されているかどうかはライブラリの品質の一部であって、この点は仕事で使う場合とても重要。日本で使う場合の難点は英語のドキュメントしかないというところか。実際に動作するサンプルコード、ライブラリのソースコードなどにアクセスできる。


GAEで使う

これを GAEで使う。まずは subversionでソースをゲット。手順は下記を参考。
Getting Started with the Closure Library - Closure Library - Google Code

チェックアウトすると closure-library-read-only が作成される。
[closure-library-read-only]$ ls
LICENSE  all_tests.html closure
README  alltests.js third_party

GAEのアプリフォルダ内にここへのシンボリックリンクを作る(※とりあえず動かす。後日デプロイする時に正式な配置を考える。)

$ ln -s /Users/hashi/development/closure-library-read-only/closure \
 /Users/hashi/development/GAE/closuresample/closure


index.html を編集して Google Closure Library 用のコードを書く。今回はダイアログを表示させてみる。

index.html
1 <html>
  2   <head> 
  3     <link rel="stylesheet" href="closure/goog/demos/css/dialog.css">
  4     <script src="/closure/goog/base.js"></script>
  5     <script>
  6       goog.require('goog.ui.Dialog');
  7     </script>
  8     <script>
  9       var fu_dialog = new goog.ui.Dialog();
 10       fu_dialog.setContent('content');
 11       fu_dialog.setTitle('File upload window');
 12       fu_dialog.setButtonSet(goog.ui.Dialog.ButtonSet.CONTINUE_SAVE_CANCEL);      
 13     </script>
 14     
 15   </head>
 16   <body>
 17     <h1>name={{ name }}</h1>
 18     <ul>
 19     {% for animal in animals %}
 20       <li>{{ animal }}</li>   
 21     {% endfor %}
 22     </ul>
 23     <button onclick="fu_dialog.setVisible(true)">open dialog</button>
 24   </body>
 25 </html>

CSS は demos 配下のものを使う(CSSを指定しないとダイアログが体をなさない)。


静的ファイル

GAE でHTMLやJavaScript, CSSなどの静的ファイルを扱うにはパスを登録する必要がある。これは app.yaml に記述する。
(参考)Using Static Files - Google App Engine - Google Code

こんな感じ。
app.yaml
1 application: closuresample
  2 version: 1
  3 runtime: python
  4 api_version: 1
  5 
  6 handlers:
  7 - url: /closure
  8   static_dir: closure
  9  
 10 - url: .*
 11   script: main.py
 12 
なお handlers: は上から評価されていくので順番を間違えると後ろの方の設定が評価されない。上の例の場合、/closure を下にすると、先に .* が評価されるので、無視されてしまう。


実行

さて実行してみよう。

ボタンを押すと

出た。

- - - -
Python も初めてだし、JavaScriptもモダンなフレームワークを使うのは初めて。もちろんGAEも初めて。初めてづくしでやることだらけ。。

2010年1月14日木曜日

GAE - Django はじめの一歩

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
GAE では Django というテンプレートエンジンが使えるらしい。試してみる。

参考:
Using Templates - Google App Engine - Google Code

ここのサンプルコードをコピペして単純なコードを書く。

main.py
19 import os
 20 from google.appengine.ext import webapp
 21 from google.appengine.ext.webapp import util
 22 from google.appengine.ext.webapp import template
 23
 24 class MainHandler(webapp.RequestHandler):
 25
 26   def get(self):
 27         animals = ['monkey', 'cat', 'dog', 'dolphin']
 28         name = 'happy catsan'
 29         
 30         template_values = {
 31           'animals': animals,
 32           'name': name,
 33         }
 34         
 35         path = os.path.join(os.path.dirname(__file__), 'index.html')
 36         self.response.out.write(template.render(path, template_values))
 37 
 38
 39 def main():
 40   application = webapp.WSGIApplication([('/', MainHandler)],
 41                                        debug=True)
 42   util.run_wsgi_app(application)
 43 
 44 
 45 if __name__ == '__main__':
 46   main()

index.html
1 <html>
  2   <body>
  3     <h1>name={{ name }}</h1>
  4     <ul>
  5     {% for animal in animals %}
  6       <li>{{ animal }}</li>
  7     {% endfor %}
  8     </ul>
  9   </body>
 10 </html>

app.yaml
1 application: closuresample
  2 version: 1
  3 runtime: python
  4 api_version: 1
  5 
  6 handlers:
  7 - url: .*
  8   script: main.py


実行するとこんな感じ。



雰囲気がわかってきた。
#インデントで何度もお叱りを受けてしまったが。。

2010年1月13日水曜日

GAE - 雛形

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
GoogleAppEngineLauncher はアプリケーション新規作成時にアプリ名とフォルダを指定すると自動的に雛形を作ってくれる。例えば closuresample というアプリを /Users/hashi/development/GAE に作ると closuresample というフォルダが生成され、app.yampl, index.yaml, main.py が自動生成される。



実行すると Hello World ! が表示される。



なおアプリケーション名に使える文字種には制限がある。エラーから判断すると文字種は次の定義のようだ(正規表現)。

'^(?!-)[a-z\d\-]{1,100}$'

アンダーバーや大文字は使えない。

困ったことに新規作成時には文字チェックが入らず実行時にエラーが出て判明する。

エラーログ内容:

ERROR    2010-01-12 11:24:14,631 dev_appserver_main.py:363] Fatal error when loading application configuration:
Unable to assign value 'closure_sample' to attribute 'application':
Value 'closure_sample' does not match expression '^(?!-)[a-z\d\-]{1,100}$'
  in "/Users/hashi/development/GAE/closure_sample/app.yaml", line 1, column 14


エラーログはランチャの "Logs" から開くことができる。



2010年1月12日火曜日

GAE 開発開始 - HelloWorld

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
GAE開発開始。以下 Mac OS X v10.6でのメモ。

アカウントは以前申し込んでおいたものを使用。

Google App Engine - Google Code


ログイン後に SDKをダウンロード
Downloads - Google App Engine - Google Code


適当なところへコピー。


実行。

これを使って簡易サーバを立ち上げ、ローカルでの開発、デプロイなどが行える。

ドキュメント Hello, World! を元にまずは HelloWorldを表示させる。
Hello, World! - Google App Engine - Google Code

/Users/hashi/development/GAE/helloworld を作成し、そこへドキュメントで紹介されていた2つのファイルを設置する(全部コピぺ)。
helloworld.py

print 'Content-Type: text/plain'
print ''
print 'Hello, world!'


app.yaml

application: helloworld
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: helloworld.py


GAEのランチャを起動し、メニューから New Application... を選択。

先程作ったフォルダを指定。

登録されたら "Run" で起動させる。

"Browse"ボタンを押すと Safari が立ち上がり、ターゲットのページを開いてくれる。

出た。最初の一歩終わり。