サイズやレイアウトがぐちゃぐちゃになった入力フィールドやチェックボックスを直す – UIComponentのインスタンスをダイナミックに作ると大変

弊社の製品「アポ助」のクライアントはFlashアプリケーションで、ActionScriptを駆使して作られています。 直感的で誰でもすぐに使える画面が好評なのですが、その直感的な操作を実現するために、その時の状態に応じて入力フィールドやチェックボックスなどを動的に生成してレイアウトしています。

ところが、このように動的にコンポーネントを生成してレイアウトするアプリケーションの場合、入力コンポーネントにUIComponentの子クラスを使うとやっかいなことになることがあります。

アポ助はクリニック用の予約管理システムなので、患者様のお名前を入力するフィールドや、診察の種類を選ぶボタンがあり、以下の画像が正しい姿です。

正しい姿
正しい姿

ご覧のように、文字やフィールドなどがきれいに整列して見易くなっています。以下が使用しているクラスです。

テキスト部分: flash.text.TextField
入力フィールド:fl.controls.TextInput
診察の種類:fl.controls.RadioButton/fl.controls.CheckBox
(fl.controlsのコンポーネントは、fl.controls.UIComponentの子クラスです。)

ところが、特定の条件において、これが次のように表示されることがあります。

サイズなどがぐちゃぐちゃ
サイズなどがぐちゃぐちゃ

一目瞭然ですが、フィールドのサイズ設定が反映されずに枠からはみ出ていますし、ラジオボタンやチェックボックスに、肝心のボタンが表示されていません。この問題はUIComponentの描画のタイミングに起因するようです。

この問題はUIComponentのdrawNow()メソッドを呼ぶことで回避できます。つまり、描画のタイミングを明示的に指示する形です。TextInputのwidthやheightの設定が反映されなかったり、チェックボックスが表示されない時などに、試してみてください。

大きなSpriteを複数ページに分けて印刷するとおかしなことになる

ひとつのSpriteの上に、大小様々ないくつものSpriteを乗せました。 そのSpriteはA4の紙よりも大きいため、印刷する際には複数のページに分けないといけません。 ActionScriptで一つのSpriteを例えば2ページに分けて印刷するには、PrintJob.addPage()を2回呼び、それぞれの第2パラメータに、1回目ならnew Rectangle(0, 0, <ページ幅>, <ページ高さ>)を渡し、2回目ならnew Rectangle(0, <ページ高さ>, <ページ幅>, <ページ高さ>)を渡します。このように、各ページにSpriteのどの部分を印刷するかを指定します。

ActionScriptの日本語メッセージを解読してみよう

ActionScriptのコンパイル時やランタイムの日本語のエラーメッセージはなかなかどうして手ごわくて、暗号なんじゃないかと思えてくる時があります。

正しく解釈できるようになるには経験値が必要ですが、全てのエンジニアがその経験をすぐに積めるわけではないですし、試行錯誤を繰り返してこそ経験値が増えるのに、その試行錯誤の副産物であるエラーメッセージの解釈に経験値が必要だなんて、鶏が先か卵が先か。しかも分かり辛いエラーほど、そのエラーの文言とはまったく無関係の初歩的なケアレスミスによって発生するものが多いのです。

この記事には、そんな、ActionScriptのコンパイルエラーを解読…ではなく解釈するための経験値の素を継続的に追加していきます。

まず最初に、これから特定のメッセージが発生した際のいくつかの考えられる原因を説明しますが、そのメッセージの原因が必ずここに説明してあるものであるとは限らないので、注意してください。同じメッセージで複数の原因がある場合があるので、ここに説明してあるものは、あくまでそれらのうちの一つとして参考にしてください。

rightparenがcolonの前に必要です。

右括弧がコロンの前に必要です、と言っているわけですが、そんなことない時でも出ます。

関数の定義の際にfunctionのキーワードを書き忘れた場合。直前までJavaでコーディングをしていると、よく出会います。

誤: private isOk(strTest:String):Boolean {
正: private function isOk(strTest:String):Boolean {


ActionScript ファイルには外部から表示可能な複数の定義は使用できません

定義を使用できません、って何か使用しているつもりはないのだけど…と混乱しがちなメッセージです。

これは、クラス変数を定義するつもりが、public class….で始まるクラス定義の外に変数の定義文を書いてしまうとこれが出ます。もちろん、賢いIDEを使っていればこのようなことは起きません。


private 属性はクラスプロパティの定義でのみ使用できます。

または、「protected 属性はクラスプロパティの定義でのみ使用できます。」

「そうですよね」と答えたくなるメッセージですが、このエラーがある日突然起き始めることがあります。それまでは大丈夫だったのに。

これは、にょろ括弧{}の不一致です。このエラーが起きた場所から遡って行って、{}を含むfunction定義を見つけて、目を皿のようにして{}を見ましょう。多分if文やループ文など、どこかのブロックが閉じていないか、もしくは余計な}があるか、というところです。


1113 Array(x) は新しい Array(x) と同様に動作します。Array 型に値をキャストするには、Array(x) ではなく式 x を Array として使用します。

「式xをArrayとして使用」って、もう、文章が完全に崩壊しています。某アインシュタインの伝記の翻訳本ぐらい支離滅裂です。

この文章は、「Array(x)と書くとnew Array(x)という意味になっちゃうよ」と注意してくれているのです。さらに、「キャストしたければArray(x)ではなく、(x as Array)を使いましょう」(Arrayのキャストにはas演算子を使う)と正しい方法を教えてくれているのです。親切にもメッセージが正しい方法を教えてくれる稀有なケースであるにも関わらず、残念な翻訳でもったいないことになっていますね。


まだまだある?!

この記事は、正しい解釈が必要なメッセージに遭遇したら今後も引き続き更新します。

Using a CheckBox in a DataGrid in ActionScript 3.0 [AS3] – I Want a CheckBox Inside a DataGrid that Behaves Like a CheckBox

There is an entry on this blog that answers questions like “How do I put check boxes inside a datagrid?” and “How do I enable multiple check box selections?”, which is one of the popular entries on this blog. The entry is in Japanese, but I recently found out in an English forum that they seem to be universal questions. Thinking the entry might help a few more people, I tried some web page translation tools on the entry, but I couldn’t figure out any of what I was trying to say by reading the translated stuff, so I decided to translate the entry into English myself.

Well, so much for the introductory remarks. Here it is.

Data manipulation is a basic aspect of business applications, so it is probably safe to assume that a GUI-providing programming language has functions and components that deal with data manipulation like listing, sorting, etc. ActionScript 3.0 does, too.

In this entry, I will explain how to put check boxes in such data lists by adding few functions to code samples in Adobe’s online documents. Let’s assume that you are making a course registration application. By using the method explained in this entry, you can change the status of multiple students in one step by ticking multiple check boxes. Some components allow you to select multiple lines by clicking on them while holding down the Ctrl key, but if you think that method is not so user-friendly, then check boxes may be the solution.

Data manipulation components are commonly made with a pattern using a data grid, a data provider and a renderer. ActionScript 3.0 uses the same pattern, and provides
fl.controls.DataGrid that displays data in a grid of rows and columns, fl.data.DataProvider that provides data to a DataGrid, and fl.controls.listClasses.CellRenderer that tells the grid how to display the provided data. By default ActionScript 3.0 provides a CellRenderer class that displays the data in text.

To change one of the columns in a DataGrid to display a check box, 1) you make a new class that inherits the fl.controls.CheckBox class and implements the fl.controls.listClasses.ICellRenderer interface, and 2) specify the new class in the cellRenderer property of the subject column. The details are explained in the “Define a custom CellRenderer class” section of “Work with a CellRenderer” page on the ActionScript 3.0 Components manual. However, the code listed on this page results in an error, so for a samples code, the one listed in the comments section on fl.controls.dataGridClasses.DataGridCell is much more useful. If you are making a CellRenderer class for the very first time, I’d recommend you to just try this sample code first. This sample code is hereafter referred to as “the sample code” in this entry.

One point that I found inconvenient with the sample code was that each check box represents the selection status of a line in the grid. So, let’s take a step forward and make the check boxes independent of the selection status by going through the modifications that need to be made to the sample code.

First, we modify the function set selected(). In the sample code, the CheckBox’s status is set here, which presents two problems:

  1. This method is called when a line in the DataGrid is selected, so the status of a CheckBox always reflects the selection status of the containing row in the DataGrid; i.e a CheckBox is ticked when a row is selected, making it not appropriate for applications like shopping carts and the aforementioned course registration program. Instead, it should toggle its status when you click on it.
  2. This method is not called when the DataGrid is first displayed, so the cell values are not reflected to the CheckBox status, making the CheckBox unchecked by default no matter what the cell value is. It is only when a row is clicked (selected) that a cell value is reflected to the corresponding CheckBox.

In order to solve these problems, a part of the logic in set selected() is moved to functions set listData() and toggleSelected() both of which will be described later. The line that sets the _rowSelected attribute remains in set selected() so that visual attributes of the DataGrid object (e.g. colors) can be changed when a row is selected.

To solve problem #1, we will modify the function toggleSelected(), for which the sample code says “don’t set selected or dispatch change event”, but for the above mentioned reasons, the selected attribute is set here. (Please note that this is only a suggestion, so please use this at your own risk. For the rest of the usual caveats, please read our “Terms of Use”.)

Now we have a CheckBox that behaves like a CheckBox; i.e. if you click on it it toggles its check mark status regardless of the selection status of the DataGrid.

In order to solve problem #2, we will take a look at set listData(). set listData() is called 1) when a DataProvider is set to a DataGrid, and 2) when something is changed in a DataGrid (when DataGrid.selectable = true). We are taking advantage of the former timing, so we are moving the logic that had been implemented in set selected() down here.

By implementing this, a CheckBox will appropriately reflect the cell value when a DataGrid is filled with values specified in a DataProvider.

By setting the newly implemented CellRenderer to a column in a DataGrid, you will start seeing check boxes instead of “true” and “false” strings.

You can use the CellRenderer like this, but if your application handles ListEvent.ITEM_CLICK events, there is one more modification to make, which is to stop CheckBox’s CLICK events to be transformed to ListEvent.ITEM_CLICKED events, because we are making check boxes that behave independently of DataGrid’s selection status, and clicking on a check box does not mean selecting the corresponding row in a DataGrid.

So, there you have it – a Checkbox in a DataGrid that behaves like a CheckBox!

A few last comments — This code is one implementation method that I derived after much trial and error, which is listed here for your reference. Please read our “Terms of Use” before using the code.

This code is being used in application that we develop, and is subject for future modifications and bug fixes.

「初めてのWindowsガジェット」ソースコード解説

【ランチタイムラーニング】 初めてのWindowsガジェット」という記事(冒頭の「注」もお読みください)で、お昼を食べながら踏み出す、ガジェット作成の第一歩について説明しました。

この記事では、その記事に掲載したソースコードについて、少し詳しく解説します。

JavaScriptでのタイマー機能の実装

最初はHTMLの開始と、CSSのスタイルの定義です。

7行目で、bodyの幅を130pxに設定しています。ガジェットがWindows Vistaのサイドバーに貼り付いている状態を「ドッキング」と言いますが、このドッキングの状態では、ガジェットの最大の幅は130pxです。

また、ガジェットをサイドバーに貼り付けず、単独でデスクトップに表示する状態にすることができ、この状態を「アンドック」と言います。

アンドックした状態では、ガジェットの幅は130px以上に設定することができます。多くのガジェットでこの設定を利用して、ドッキングの状態では簡易的なビュー、アンドックした状態ではリッチなインターフェイスを持ったビュー、というようなビューの切り替えを提供しています。ただし、アンドックした状態でも、ガジェットのサイズは縦横共400pxを超えないことをMicrosoftは勧めているそうです。

さて次にHTMLを見てみましょう。

4行目が経過時間を表示するエリア(nowTime)です。そして、5行目に設定時間を入力するフィールド(setTime)があり、6行目、7行目がタイマーを開始、停止するためのボタンです。開始するにはJavaScriptで記述したstartTimer()ファンクション、停止するにはfinish()ファンクションをそれぞれ呼ぶようになっています。

1行目で、このHTMLがロードされたときにJavaScriptで記述したinit()ファンクションを呼ぶようになっていますが、後で出てくるように、今回のガジェットではこのinit()ファンクションは何もしないので、このHTMLがロードされたときは特別な処理は行われません。しかし、今後タイマーの背景画像を変えたりするなどカスタマイズするときに、HTMLがロードされるタイミングでJavaScriptのファンクションを呼ぶ、ということを覚えておきましょう。

最後にJavaScriptを見てみましょう。

ここでは経過時間の常時を更新し(26行目)、毎秒JavaScriptのsetTimeout()でつぎのちょうどの秒にdoSecTimerを呼び出します(30行目)。念のため高負荷がかかっていて表示の次のちょうどの秒が過ぎてしまった場合には単に0.1秒後に再度更新するようにします(32行目)。これをsetTimeout()で設定時間までの時間を計る(39行目,44行目)ことでタイマーを実装しています。

表示の更新は、その時点での時間と開始時間の差分をとって、何秒経過したかを計算します。もちろん1秒ごとに1を足すのが一番簡単ですが、タイマーイベントがジャストの時間に発生しなかったり、そのほかの計算での時間も足されてしまうのでどんどんどんどん遅れることになり、やめたほうが良いでしょう。

また、前述の通りこのガジェットではHTMLがロードされたときに呼ばれるinit()ファンクションでは何もしませんが、7行目、8行目でコメントアウトしてある行のコメントをはずして、背景画像を表示することができるでしょう。

ガジェットでのalertの実装

さてタイマーはこれで実装できるのですが、そもそもタイマーは、指定時間が経過したことを「ぴぴっ」とか言いながら教えてくれてこそ、その本領を発揮できると言うものでしょう。なのにこのタイマーにはアラーム機能がありません。まるで人ごとのように書いてしまいましたが、このセクションでは簡単なアラーム機能を実装しましょう。

そもそも何故このタイマーガジェットはalert()ファンクションを使って、ひょいっとポップアップさせることさえしないのか。それは、alert()ファンクションやconfirm()ファンクションで出てくるポップアップがWindows Vista User Experience Guidelines for the Sidebarに則っていないということでサイドバーガジェットでは無効化されているからです。

それでもとりあえず簡単にポップアップを出したいときもあるではないですか。デバッグするときなんか特に。MSDN Magazineの記事に、そんな開発者の心の叫びに応えた、alert()やconfirm()と同等の機能を実装するやり方(ガジェットプラットフォームが脆弱である一因)が掲載されています。以下が今回のタイマーガジェットにそのやり方を適用する方法です。

ステップ1: ファンクションを準備する

作業フォルダに新しく「Timer.vbs」というファイルを作成して、次のように記述し保存します。

ステップ2: タイマーガジェットから呼び出す

Timer.htmlの中で、前述のCSSの直後、JavaScriptの直前に次の行を書きます。

同じくTimer.htmlの中の、finish()ファンクションの最初か最後に次の行を書きます。

これで簡単なアラーム機能ができました。

参照情報

【ランチタイムラーニング】 初めてのWindowsガジェット – お昼を食べながらガジェットを作ってみよう – Windows 7 デスクトップおよびVista サイドバー

「ガジェット」という言葉を聞くと、昔のアニメ、Inspector Gadgetの決め台詞、”Go-Go-Gadget!”と叫びたくなります。この台詞と共に、体のあちこちからわらわらとガジェットが出てくる様は、さながら洋風ドラえもんといったところです。

GUIを伴うアプリケーション作成は数年前まではちょっと敷居が高いものでしたが、現在ではエディターと初歩的なHTMLやJavaScriptの知識があれば、便利な「ガジェット」がいとも簡単に作れるようになりました。しかも作ったガジェットを世界中の人たちと共有できる環境があるので、その便利さや自分の作品を公開し使ってもらえる楽しさから、文字通り老若男女が挑戦しています。

最初の一歩はお昼を食べながら踏み出せるくらいの手軽さです。明日のお昼にでも、ちょっと作ってみませんか?


注: 脆弱なガジェットをインストールした場合に遠隔からコードを実行させることができてしまうプラットフォームである(KB2719662)との理由でWindows 8以降での機能実装の打ち切り、およびガジェットを無効にするように薦めています(理由は不明ですがガジェットを無効にするためのお手軽Fix it 50906の提供が中断か終了したようなので、無効にする場合は上記記事の中のSuggested Actionsの抜粋 Windows サイドバー ガジェットの悪用から Windows Vista および Windows 7 コンピューターを保護する方法 を参照してください)。ガジェットはお手軽ですが、動作させることはexeを動作させているのと同じ危険性を持つので、由来のわからないものや、由来がわかっていても脆弱かもしれないという意識が必要です。またローカルファイルにアクセスする権限やコードの実行権限があるので、脆弱なものを作ったりインストールしたりしたら大変なことに、しかも管理者権限でログインしていたらOSまるごと乗っ取られるかもしれませんよ、ということになります。以上、当たり前な話であるわけですが、テキストエディタだけでお気楽に作れる分余計に注意が必要、ということでしょうか。メールに添付されたzipの内のjsファイルを実行してしまってファイルを軒並み暗号化されて、復号のためにはbitcoin払えと表示されて涙、と似たようなものです(こちらはOSによる注意のダイアログが出る分少しましかも知れないですが、見慣れていて結局そのままOK押してしまうかも)。


何を作るか

Windows サイドバー ガジェット開発者ガイドには、”Hello, World!”と出てくるガジェットの作り方が掲載されています。”Hello, World!”はチュートリアルの王道ではありますが、もう少し実用性のあるガジェットを作ったほうがより楽しく作れるでしょう。

例えばタイマーなどは便利な上に簡単です。最近、仕事を効率よく進めるコツとして「ライフハック」という言葉が使われていますが、いくつかのライフハックの中で1日の時間を分割して効率良く作業を進める方法を取り上げています。ただ、時間を気にしながら作業をしても集中できないので、タイマーがあると便利です。それにタイマーはエンジニアの友であるカップ麺を作る時にも重宝します。

そこで今回は簡単なタイマーを自作します。この簡単なタイマーを改造していけば、自分好みのタイマーを作ることができます。

材料を準備しましょう

【材料】

  • お気に入りのエディタ (Windowsのメモ帳(notepad.exe)で十分)
  • ブラウザ

以上です。そうです、今この記事をご覧になっているのであれば標準的にコンピュータに入っているもので作れてしまうのです。それがガジェット作りの手軽さなのです。

もちろんJavaScriptやHTMLのリファレンスが手元にあると便利ではありますので、お好みでご利用ください。

さっそくガジェットを作りましょう

手順と成果物の概要

ではさっそくガジェットを作りましょう。その手順は以下の通りです。

  1. %LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgetsにフォルダーを作る→「○○.gadget」フォルダー
  2. JavaScriptを含んだHTMLを記述する→「○○.html」ファイル
  3. マニフェストを記述する→「gadget.xml」ファイル

以上、簡潔な3ステップです。

ステップ1: 作業フォルダの作成

%LOCALAPPDATA%\Microsoft\Windows Sidebar\Gadgets (C:\Users\<ユーザー名>\AppData\Local\Microsoft\Windows Sidebar\Gadgets)に「Timer.gadget」フォルダー(以降、作業フォルダーと呼びます)を作成します。

ステップ2: JavaScriptを含んだHTMLを記述する

作業フォルダーに、新しく「Timer.html」というファイルを作成して、次のように記述し保存します。(このHTMLファイルの内容の詳しい解説は、『ソースコード解説』に記述しましたので、必要に応じて参照してください。)

ステップ3: マニフェストを記述する

作業フォルダーに新しく「gadget.xml」というファイルを作成します。

作成したファイルに次のように記述し保存します。Shift_JISの代わりにUTF-8で保存できるエディタの場合はencoding=”…”の部分は不要です。

ガジェットを動かしましょう

Windows Vistaの場合

サイドバーを右クリックで「ガジェットを追加」を選びます。

Windows 7の場合

Windows 7の場合はデスクトップの右クリックで「ガジェット」を選びます。

するとガジェットのリストに、「Simple Timer」が出てくるので、それを選びます。

パッケージを作る場合

作成した「Timer.html」「gadget.xml」の2つのファイルをzipにまとめます。zipにフォルダ名が保存されないように(zipファイルをダブルクリックした際に、フォルダではなくて2つのファイルが見える状態)、作成してください。そしてできあがったzipファイルを、「Timer.gadget」という名前に変更します。出来上がった「Timer.gadget」ファイルをダブルクリックしてインストールできるパッケージができます。

さあ、いかがですか?ちょっと見た目が悪いタイマーっぽいものが出てきましたね?

そして自分好みのタイマーに

今回作成したタイマーは、ガジェットの作り方の基本だけなので装飾していません。自分好みの背景画像や、色、フォント、さらにアニメーションを加えて、自分好みのタイマーに育ててみましょう。それがアプリケーション作りの醍醐味のひとつです。

また、このタイマーには指定時間が経過したことを通知するアラーム機能がありません。簡単なアラーム機能に関しては、上記のHTMLファイルを解説した「『初めてのWindowsサイドバーガジェット』ソースコード解説」という記事に記述しましたので、必要に応じて追記してみてください。

そうしているうちにガジェットのJavaScriptは原型を留めないほど変わるでしょう。その頃にはタイマーに限らず、自分の好きなガジェットが作れるようになっているはずです。楽しいガジェットを作って、世界に向けて発信しましょう!

参照資料

ActionScript3.0のDataGridでCheckboxを使いたい [AS3] – Checkbox CellRendererを作る

Using a CheckBox in a DataGrid in ActionScript 3.0 [AS3](⇐ In English)

ビジネスアプリケーションにとってデータの操作は基本中の基本。だから、GUIコンポーネントを提供する言語だったら、データをリスト表示したり並べ替えたりする機能やコンポーネントがある、と想定してもおかしくありません。ActionScript3.0にもあります。

今回はActionScript3.0で、そのリスト表示の中にチェックボックスを表示する方法について、Adobe社のオンラインドキュメントに掲載されているサンプルに追加機能を加えながら解説します。これができると、例えば社員教育の受講管理で、リスト上で受講ステータスチェックボックスにチェックを入れればその人を受講済みにできたり、複数のレコードを選択して処理する場合に、処理チェックボックスにチェックが入っている行だけ処理をする、などということができます。もちろんコントロールキーを押しながらクリックして複数選択する、という手もありますが、「これってユーザに優しくないよね」と常日頃思っている人には、チェックボックスのほうが良いかもしれません。

データのリスト表示や操作をするコンポーネントは一般的に、データ部分を提供するものと、そのデータの表示の仕方を指定して操作するものとに分ける、というパターンを使って作られていますが、ActionScript3.0もそのパターンで、データをグリッド(grid)表示するDataGrid、そのDataGridにデータを提供(provide)するのがDataProvider、そして、DataGridのそれぞれの列やセルの表示/描画の仕方を指示する(render)のがCellRenderer、という組み合わせになっています。デフォルトではデータをテキスト表示をするCellRendererが提供されています。

このDataGridのひとつの列をCheckboxにするには、fl.controls.CheckBoxクラスを拡張してfl.controls.listClasses.ICellRendererインターフェイスを実装した新しいクラスを定義し、チェックボックスにしたい列のcellRendererプロパティに、そのクラスを指定します。詳細なやり方はActionScript3.0のマニュアル「カスタムCellRendererクラスの定義」の「ICellRendererインターフェイスを実装するクラスを使用してカスタムCellRendererを定義するには」のセクションに記載されています。しかし、このページに掲載されているサンプルは動かすとエラーになるので、その代わりに、「DataGridCellEditorのオンラインマニュアルの(なぜか)コメント欄に記載されているコード例が一番参考になるでしょう。CellRendererを作成するのが初めてのかたは、まずはこのコード例を、そのまま試してみることをおすすめします。

このコード例ではDataGridの選択状況がチェックボックスと連動する作りになっています。今回、著者はチェックボックスが独立して機能するようにしたかったので、この記事ではこのコード例をベースに、その変更点について解説します。

では変更点を見ていきましょう。まずはfunction set selected()です。Adobe社のコード例では、ここでチェックボックスの選択状況をセットしていますが、このメソッドは、DataGridの行が選択された際に呼び出されます。一番最初にDataGridを表示した時点では、このメソッドは呼び出されないので、セルの値がチェックボックスにチェックに反映されず、チェックボックスは常にチェックが入っていない状態で表示されます。セルをクリックして初めてセルの値がチェックボックスに反映されます。また、ここでチェックボックスの選択状況をセットすると、DataGridの選択状況とチェックボックスの選択状況を連動させることになるため、ショッピングカートや冒頭で例示したような「社員教育受講管理」など、チェックボックスが単独で機能しないといけない場合に対応できません。DataGridの行を選択したらチェックが入るのではなく、チェックボックスをクリックしたらチェックが入ったりはずれたりして欲しいのです。なので、このロジックは後述のfunction set listData()とtoggleSelected()で実装します。ただし_rowSelected属性をセットしている部分は、DataGridを選択した際に表示色などを変えるときに使うので、残しておきます。

次にtoggleSelected()ですが、Adobe社のコード例では”don’t set selected or dispatch change event.” (selected属性に値をセットしたり、CHANGEイベントを送出しないように)と書いてありますが、上記のset selected()で記述した理由で、selected属性はここでセットします。

これで、DataGridの選択状況とは関係なく、チェックボックスをクリックすれば正しい値がセットされる、チェックボックスらしい動きになります。もう一つやりたかったのは、DataGridを最初に表示したときにセルのBooleanの状況を正しくチェックボックスに反映することです。それがもう一箇所の変更点set listData()になります。set listData()は、DataProviderがDataGridにセットされるタイミングと、DataGridで何か変更が起きるタイミングの2箇所で呼び出されます(DataGrid.selectable=trueのとき)。その前者のタイミングを利用したいので、上記のset selected()で実装するはずだったロジックをこちらに移動するわけです。

これでDataGridの初期値がDataProviderのデータで埋まったときに、チェックボックスがセルの値を正しく表すようになります。

上記の変更を加えたCellRendererをDataGridのカラムにセットすれば、”true”や”false”という文字列の代わりにチェックボックスが表示されるようになります。このままでも使えますが、もしDataGridのListEvent.ITEM_CLICKイベントを拾って処理をするアプリケーションに使う場合は、最後にもう一工夫必要です。それはチェックボックスのCLICKイベントがListEvent.ITEM_CLICKEDに変換されるのを止めることです。なぜなら、今回実装しようとしている、DataGridとは連動せず単独に動作するチェックボックスの場合、チェックボックスをクリックするという行為の目的は、チェックボックスの値を変えることであり、DataGridの行を選択する、という目的ではないからです。

これでOKです。

ところで、どこかのフォーラムの書き込みで、Adobe社のサンプルを見て「こんなに長いコードを書かないといけないの?!」と驚いている人を見かけました。確かにぱっと見ただけですと、ただチェックボックスを表示したいだけのわりには長く見えるかもしれませんが、要点はこの記事に書いた点だけで、他の6~7割のコードは全て表示スタイルに関するものです。まずは表示スタイルは何もいじらずそのままにして使ってみると、見た目ほど複雑ではないことに気が付かれると思います。

なお、このコードは著者がアプリケーション開発の過程で試行錯誤の結果導き出した一つの手法であり、皆様の参考用に掲載しているものです。ご
利用の条件につきましては、「サイトのご利用条件」をご一読ください。また、このコードは弊社が開発しているアプリケーションで実際に使われています。したがいまして、今後改善やバグ修正がされる可能性がありますが、変更が入りましたら随時この記事を更新します。

LimeSurveyをインストール

オープンソースのアンケートシステム、LimeSurveyをFreeBSDにインストールしました。いつもの「実験君」です。データベースにはPostgreSQLを使います。

まだ使い始めたばかりなので、LimeSurvey自体についての感想や応用方法については後日に取っておきます。今回は現時点でマニュアルには載っていなかったインストールに関する情報を補足します。なお、この情報はLimeSurveyのForumにも投稿し、投稿後に気づいたこともこのブログとForumの両方に追記するようにしていますが、こちらのブログの内容が最新情報になります。

FreeBSD&PHP5.2&PostgreSQLという組み合わせでLimeSurveyを導入するには、以下の3つのPHPのextensionが必要になります。

  • PGSQL

これを入れないと、データベースに接続できず、インストールスクリプト(/limesurvey/admin/install)を実行した直後に”Database connection failed”というエラーメッセージがブラウザ上に表示されます。

  • SPL

これを入れないと、インストールスクリプト(/limesurvey/admin/install)を実行した直後に”ArrayObject not found”というエラーメッセージがブラウザ上に表示されます。SettingsStorageというクラスがArrayObjectを継承して定義されているからです。

  • CTYPE

これを入れないと、新しいアンケート(survey)を保存する際に、”Fatal error: Call to undefined function ctype_alnum()”というエラーメッセージがブラウザ上に表示されます。

他はマニュアル通りで問題なく動き始めたのでかなり幸先が良く、フォーラムも活発で、UIや機能も大分頑張って作った感がにじみ出ているので、かなり期待しています。

使用感や応用についてはまた後日ご報告します。

/limesurvey/admin/install

その「名前」、あなたのものですか?(その2)

この記事は「その『名前』、あなたのものですか?(その1)」の続きです。

あるお客様が、会社のウェブサイトの引越しをしたい、とおっしゃいました。 この場合、一番基本的な進め方としては、サイトのコンテンツを構成するファイル達を別のサーバに移動して、URLが新しいサーバを示すように変更する、と いうものです。しかしこのお客様の場合はそれが(すぐには)できませんでした。前回の記事は「ドメイン名」について解説しました。

前回のポイント

  • ドメイン名 ≒ 唯一無二の苗字
    • 唯一無二だから好き勝手につけられない。→レジストラから入手するもの。
  • IPアドレス ≒ 住所
  • ネームサーバ ≒ 住所録
    • ドメイン名に対するIPアドレスを知っているネームサーバをレジストリに登録する。
    • 苗字を変えずに住所だけ引っ越すことができる。

今回は実際の引越しについて解説します。

人が引越しをする理由は様々です。間取りが狭くなった、新しい設備が欲しい、建物が無くなる、などなど。ウェブサイトのサーバを引越しする理由も大して変わりありません。そして、人が引越しをするときは、トラックで中身を移動して市役所に転出・転入届を提出しますが、ウェブサイトのサーバの引越しも基本的には中身を移動して住所変更をするだけです。

では、弊社サイトである「www.abacustech.co.jp」を引っ越すと仮定した例で考えてみましょう。前回の記事の例では、このサイトのコンテンツ(文章や画像などのページの内容)は198.51.100.88というIPアドレス(住所)のサーバに置いてありました。今回は、これらのコンテンツを203.0.113.7という「住所」にあるサーバに移動したとしましょう。

図1 サーバの引越し
図1 サーバの引越し

ドメイン名「abacustech.co.jp」は レジストラから株式会社Abacus Technologiesの名義で入手し(図1の(1))、Abacus Technologiesが操作できるネームサーバを登録しています(図1の(2))。そこでAbacus Technologiesはネームサーバに新しいIPアドレス(203.0.113.7)を登録します(図1の(3))。これは皆さんが引っ越した際に転居届を出すのと似ています。

この処理が終わると、ネームサーバは「www.abacustech.co.jp」について聞かれたら、新IPアドレス(203.0.113.7)を教えるので、ユーザのコンピュータからは正しく、引越し先である203.0.113.7のサーバへ要求がたどり着くのです(図1の(4))。

この処理が正しくできたのは、直接的には、レジストリに登録されているネームサーバをAbacus Technologiesが操作できたからなのですが、そもそも操作できるネームサーバが登録できたのは、以下の条件が揃っていたからです。

  1. abacustech.co.jpがAbacus Technologiesの名義である(管理のためのメールが届く)
  2. レジストラに登録されているドメイン名の登録内容の変更権限(*1)をAbacus Technologiesが持っているので、Abacus Technologiesが操作可能なネームサーバを指定できる

通常、変更権限を持つ人はそのドメイン名の名義人、もしくはその名義人から委託された人になります。この2つの根本的な条件が揃えば、ドメイン名の登録IPアドレスはいつでもどこにでも変更できます。

そこで質問です。皆さんがウェブサイトを公開しているそのドメイン名、名義人とドメイン名の登録内容の変更権限を持つ人は誰ですか?

ウェブサイトを制作する際に、その作業を業者に委託すると、ドメイン名の取得も代行してくれる業者が多いです。もしドメイン名の取得も委託する場合は、ドメイン名の名義人と、登録内容の変更権限を持つ人が誰かを確認しましょう。そして、もし将来的にサーバの引越しの自由度を視野に入れるのであれば、できる限りドメイン名の名義と登録内容の変更権限を持つ人が自分になること、もしくはその名義や変更権限が移管できることと、その移管プロセスが明確であることを確認しましょう。

ドメイン名が自分のものであれば、もちろんサーバに縛られることなく自由に処理できます。もしドメイン名の名義人でなかったり変更権限がなければ、仮にサーバを引越ししたくなっても、ドメイン名の名義人や変更権限を持つ人が許可しないと引っ越せません。もし許可が無くても引っ越したければ、別のドメイン名を取得することになり、それは苗字が変わるのに似たインパクトがありますが、このインパクトについてはまた別の機会に解説します。

ドメイン名の名義人になると、その管理にはドメイン名によって年間で数百円から数万円の管理費がかかります。ドメイン名は、不要になれば放棄できます(ただし一度放棄したら、後日同じドメイン名を再度取得したくなっても、それができる確証はありません)。また公共性の高いサイトや大人気のサイトの場合は悪い人が取得してmalwareの配布に利用される恐れもあります。

ドメイン名は唯一無二の苗字と同等で、時間が経って周知されればされるほど組織や会社の呼称の一つとして大事なものになります。ウェブサイトを制作する際や、会社のドメイン名を取得する際には、ドメイン名の名義人と管理について以上の要素を包括的に検討されることをお奨めします。

ここがポイント

  • ドメイン名の名義人であり変更権限があれば好きに操作できる
  • IPアドレスはいつでもどこにでも変更できる
    • →苗字を変えずに住所だけ好きに引越し可能!(*2)

(*1) 少し専門的な言葉を使うと、ドメイン名の登録内容とは「whois」の内容のことです。ドメイン名の内容の変更権限を持つ、ということは「whoisの内容の変更権限を持つ」ということで、レジストラによってその権限の付与の仕方が異なります。例えばMelbourne ITというレジストラだと、変更権限を持つユーザはユーザIDとパスワードを使ってシステムにログインして管理します。

(*2) ただしそのサーバが利用できる立場でないといけません。引越し先の物件を賃貸契約していないと引っ越せないと同じです。

注意: この記事内のIPアドレスは全て説明用のダミーのIPアドレスです。このようなIPアドレスについては「文書に記述するときに使って良い説明用のドメイン名、IPアドレス」を参照してください。

その「名前」、あなたのものですか?(その1) – ドメイン名とは何ですか?

仕事用のウェブサイトをドメインも含めて誰かにお任せで作られる方へ: ドメインを含むURLなどを長く使い続けたい場合は、なんだかよくわからなくてもぜひドメインの「登録者(Registrant)」(属性JPの場合は[登録担当者]、汎用JPの場合は[公開連絡窓口])および「管理者(Admin)」のメールアドレスは、完全にコントロールできる権限が自分だけにあり、かつ@以降にそのドメインを含まないメールアドレスを指定してもらってください。御自身で利用しているプロバイダがメーリングリストを提供している場合もあるので、そういったサービスを利用して自分とお任せする方へ自動的に転送されるようなメーリングリストのアドレスを作成すると便利かもしれません。ドメイン登録者のメールアドレスの確認はwhoisというものでできます。廃業される方も多いので何年か後に泣かないで済むかもしれません。


あるお客様が、会社のウェブサイトの引越しをしたい、とおっしゃいました。この場合一番基本的な進め方としては、サイトのコンテンツを構成するファイル達を別のサーバに移動して、URLが新しいサーバを示すように変更する、というものです。しかしこのお客様の場合はそれが(すぐには)できませんでした。そこで2回に分けてウェブサイトの引越しについて解説します。今回は「ドメイン」について解説します。

例えば弊社のサイトを見るためには、ブックマークに登録していただいたリストの中から「株式会社Abacus Technologies」をクリックしたり、http://www.abacustech.co.jp/とURLを直接入力したり、検索結果から弊社のサイトのページを選んでいただいていると思います。いずれの場合も、皆さんのコンピュータは「www.abacustech.co.jp」にアクセスしようとします。

ドメイン名の使われ方
図1 ドメイン名の使われ方

図1の(1)でユーザーが見たいウェブページを指定するために使っているwww.abacustech.co.jpのabacustech.co.jpの部分が「ドメイン名」と呼ばれるもので、「ドメイン名」は「苗字」の役割を果たします。つまり「abacustech.co.jpさん」と呼んでいると思ってください。ただしこの「苗字」は唯一無二という特性があり、他に同じ苗字を持つ人はいません。そして、みんなが好き勝手に名前を付けていたら唯一無二にはならないので、ドメイン名は「レジストラ」から入手することになっています。なお、説明書などで例示するときに使えるドメインは「文書に記述するときに使って良い説明用のドメイン名、IPアドレス」をご参照ください。

さて、苗字を知っていても住所を知らないので、ユーザーはそのページが実際にどこにあるのかは知りません。そこで登場するのが「ネームサーバ」です。「苗字」の役割を果たすドメイン名に対して、ネームサーバは「住所録」の役割を果たします。つまりネームサーバが「www.abacustech.co.jpさん」がどこに住んでいるのか、その「住所」を見つけてくれるのです。その「住所」の役割を果たすのが「IPアドレス」と呼ばれるものです。IPアドレスは物理的に存在する機械に対して割り振られています。したがって、住所録であるネームサーバに聞けば「www.abacustech.co.jpさん」の住所が「198.51.100.88」(*1)であることが分かるので(図1の(2))、コンピュータはそのIPアドレスを指定してウェブサイトのページを要求することができるのです(図1の(3))。

でも、そもそも「www.abacustech.co.jpさん」の住所が記載されている住所録はどこにあるのでしょうか。その情報を管理しているのが「レジストリ」です。レジストラからドメイン名を入手すると、管理情報の一つとして、レジストリにそのドメインの情報を管理するネームサーバをレジストラ経由で登録できます。ネームサーバはレンタルサーバの業者が提供するもの、レジストラが提供するもの、他にも相当気合があれば自分でサーバを運用する、などがあります。

ところで、このトピックのそもそもの目的は「ウェブサイトの引越し」でした。皆さんが引っ越した場合には、市役所で転出・転入届けを出して、新しい住所を届け出ますね?市役所が駅から遠い所にあるとちょっと面倒ですが、これをしないと住民票が移動しません。さて、そう考えると、ドメイン名に関しても、「苗字」(ドメイン名)があって「住所」(IPアドレス)と「住所録」(ネームサーバ)があるということは、「要するに住所録を書き換えれば良いのか?」と想像できるのではないかと思います。それで正解です。つまり苗字を変えずに住所だけ変えることができるのです。

では次回はその引越しについてご説明しましょう。

ここがポイント

  • ドメイン名 ≒ 唯一無二の苗字
    • 唯一無二だから好き勝手につけられない。→レジストラから入手するもの。
  • IPアドレス ≒ 住所
  • ネームサーバ ≒ 住所録
    • ドメイン名に対するIPアドレスを知っているネームサーバをレジストリに登録する。
    • 苗字を変えずに住所だけ引っ越すことができる。

(*1) IPアドレスは一つのドメイン名に対して複数登録できます。また一つの機械(ネットワークインターフェース)に対して複数のIPアドレスを割り振ることができます。さらには複数の機械に一つのIPアドレスを割り振る(エニーキャスト)こともできますが、一般人がインターネット上でエニーキャストを運用することはありません。

注意:

PivotXでファイルのアップロードをする時は

PivotXのCommunityでもファイルのアップロードについて度々話題になっているようです。アップロードの設定は場合によっては若干複雑になります。 そうこうしているうちに自分もその仲間入りをしてしまいました。 php.iniの次の行がOnになっていること。

file_uploads = On

php.iniの次の行が指定しているディレクトリが存在していること。

upload_tmp_dir = “/phptmpdir”

upload_tmp_dirが指しているディレクトリ(上記の例だと/phptmpdir)はhttpdのプロセスオーナーが読み書きできるようにアクセス権が設定されていること。 この設定ができていないと、新しいエントリーを作成中にイメージをアップロードする操作をしたときに、Complete(完了)というメッセージが出るものの、イメージディレクトリには何もできません。

PivotXで最新の記事のリストを表示したい

PivotX を使い始めて数ヶ月が経ち、記事も順調に増えてきました。そして、記事が増えることで新たに発見した使い方や、追加で欲しい機能が出てきて、日々楽しく試行錯誤をしています。

その一つが「最近の記事」のリストです。

一般的なブログには画面上のどこかに「最近の記事」セクションがあるものが多いですね。 PivotX では「最近のコメント」をリスト表示するタグはあるものの、記事に関してはありません。でも、 PivotX で避けては通れないタグのひとつ、 subweblog を使ってブログ内の記事リストの表示フォーマットを好みの形に指定できます。そして、複数の subweblog タグを使えば、メインの部分のリストにはタイトルと日付とイントロダクションを表示して、サイドバーには同じ記事のタイトルのリストだけを表示する、ということができ、「最近の記事」セクションを作ることができます。このやり方に関しては PivotX Support Forum でも取り上げられています(参照: “List of latest posts“)。

ただ、一つ注意しなくてはいけないのが、同じページの subweblog タグは、同じページングの影響を受ける、という点です。つまり上記の参照にあるような指定の仕方だと、トップページから「次のページへ」ボタンを押すと、もちろんメインの部分には次のx個の記事のリストが表示されますが、サイドバーのリストも次のx個の記事について表示されます。つまり「最近の記事」のつもりで作ったリストが全然最近ではなくなってしまうのです。

そこで上記の参照の例に追加して、最近のリストを表示するための subweblog タグに

ignorepaging="1"

というオプションを指定します。このオプションを指定することで、その subweblog タグの中身はページングの影響を受けず、常にリストの頭から表示されます。

2010年2月23日の時点で、PivotX のオンラインドキュメントでは ignoreoffset というオプションが掲載されていますが、このオプションは動作しません。PivotX Support Forum で確認したところ、どうやらこの記述は間違いのようですので、ignorepaging を使いましょう (参照: “How do you use the ignoreoffset option in subweblog?“)。

_sub_sidebar.htmlのお好みの場所に以下のコードを入れると、サイドバーに最近の記事のタイトルをリスト表示することができます。(*1)

注釈:

  1. recent という subweblog はデフォルトのテンプレートで指定されている standard とは別に定義しました。

PivotXのユーザ登録で”_”(アンダースコア)が使えない

PivotXのマニュアルやヘルプによるとアンダースコアが使えるはずなのですが、Administration → Usersから登録しようとすると、入力時にアンダースコアが”-“(ハイフン)に自動的に置換されてしまいます。

pivotx/includes/js/pivotx.jsのsetSafename()を修正すれば良いのですが、サーバー側のコードのバリデーションが足りないことにも気付きました。JavaScriptの修正と合わせて、2009/5/19のpivotx-latest.tgzとsvnリリース2278用にパッチを作って報告してみました。