HTML5のドラッグ&ドロップでファイルを扱う
HTML5のドラッグ&ドロップのうち、OSのファイルをドラッグしてHTMLにドロップする使い方について調べました。
前回のエントリーで説明したように、ドラッグ&ドロップはドラッグ側とドロップ側に分かれていて、今回はドロップ側の実装だけで済みます。(基本的なドラッグ&ドロップの実装は、前回のエントリーを参照してください)
続きを読む…
HTML5のドラッグ&ドロップのうち、OSのファイルをドラッグしてHTMLにドロップする使い方について調べました。
前回のエントリーで説明したように、ドラッグ&ドロップはドラッグ側とドロップ側に分かれていて、今回はドロップ側の実装だけで済みます。(基本的なドラッグ&ドロップの実装は、前回のエントリーを参照してください)
続きを読む…
HTML5対応のブラウザで利用できるドラッグ&ドロップの使い方を調べてみました。
ドラッグ&ドロップの実装は、ドラッグ側とドロップ側に分けて考える必要があります。HTML内の要素をドラッグして同じHTML内にドロップするのであれば両方必要ですし、OSのファイルをドラッグしてHTMLにドロップするのであればドロップ側の実装だけで済みます。
それでは、HTML5でのドラッグ&ドロップ実装がどうなるのか見てみましょう。
続きを読む…
RSS+ReaderをOperaMobile9.5に対応させる際に発見したバグを報告しておきます。
OperaMobile9.5はiPhoneのSafariと動作が近く、多分に意識して開発されたブラウザで、8.x系から大幅に仕様が変更されているためにバグも多く含まれてしまったのだと推測しています。
iPhoneのSafariと同様にviewportのmetaタグが使えます。 ただし、width=device-widthとheight=device-heightを指定すると、320×240のQVGA相当の画面になってしまいます。
ちなみにwindow.screenのwidthとheightの属性も同じく320×240でした。 これはTouchDiamondとOperaMobile9.5の組み合わせだけがこうなるのかどうかは不明です。
あとバグではないのですが、viewportのmetaタグでuser-scalable=noを指定しても拡大縮小できてしまいます。 Opera開発者曰く、拡大縮小はユーザが選択するべきものだからだそうです。
画面をスクロールさせた場合、ほとんどのブラウザではその位置を特定できるのですが、OperaMobile9.5は見当はずれの位置を返すことがあるため信用できません。 特に上にスクロールしたときや、カーソルでスクロールすると、見事に変な座標を返します。
また、現在の画面の高さを、window.innerHeight、documentElementやdocument.bodyのclientHeightなどで取得することが出来ません。 これらは仮想Viewの高さを返してくれます。
8.x系ではキチンと機能していたfixedですが、9.5からスクロールに引きずられるようになっています。 スクロール後にfixed位置で再表示しようとしますが、ずれることが多く、使い物になりません。
あとabsoluteレイヤ上の要素の座標を特定しなければいけない場面があったのですが、見事に0を返してくれました。 これも同じく使えません。
フローティングのdivエリアがスクロールできる状態の時、8.x系ではその部分をドラッグしてスクロールできましたが、9.5では出来ません。 お飾り的なスクロールバーが付いているのですが、もの凄く細くてとても使えません。
URL横にあるリロードのボタンが誤動作について。 上部のURLバーは自動で隠れるのですが、隠れたバーに重なるリンクをクリックすると、隠れたはずのリロードボタンが反応することがあります。
追記: 時々XMLHttpRequestのPOSTデータの本文が送られないことがあるようです。 稀に発生することなので原因がよく分かりませんが、そのままでは困るので対処が必要です。
以上ですが、他にもたくさんバグが隠れているような気がします。
制御コードは普通ASCIIの00-1F辺りに配置されているが、UNICODEの一般句読点付近に配置されている制御コードにも注意が必要だ。
JSONデータのやり取りでUNICODEの制御文字が入っていると、JavaScriptで文字列を展開することができない。 例えば、2028のLINE SEPARATOR, 2029のPARAGRAPH SEPARATORが混入していると、JavaScriptの文字展開ができずに例外が発生する。 (ただしIEでは問題なく処理できる)
RSS ReaderのWebアプリを実行している関係で、変な文字コードを含んだテキストに遭遇することが間々ある。 たぶん海外のテキストエディタか文字変換ツールを通して変な制御文字が混入するのだろうとみている。
今回はSEPARATORコードしか検証していないが、その他の制御コード(RightToLeftOverwrideとか)もダメな可能性が高い。 本当はJavaScriptエンジンで対応してもらうのが正しいことなんだけれど、仕方なくソフト側で対応することにした。
IEで利用できるuserData behaviorは、ユーザのローカル領域に任意のデータを保存する仕組みとしてよく知られています。 WEBの仕様ではuserDataよりも、Firefox2以降でサポートされているDOM:Storageの方がより標準に近い仕様ですが、IEを無視できないので両方に対応するケースがほとんどです。
これまでの実装は、userDataはsetAttribute、DOM StorageはsetItemでテキストデータを保存するのが通例でした。 この方法の問題点は、保存するデータが大量の繰り返しデータのときに、その一部分のみを変更しにくい点にあります。
実際にRSS+リーダーでは、履歴とクリップの処理に利用していましたが、データの追加や削除が発生するたびに、全体のデータを再構築して保存するテキストを作成していました。
ある時、何気なくuserDataの仕様を調べていたときに、XMLDocumentというプロパティがあることに気が付きました。 このプロパティを使うと、userDataの保存データをDOMで操作することができます。
DOMが使えるということは、各繰り返しのデータ一つ一つをエレメントとして設定することが可能ということです。 一部のデータを変更したければ、該当するエレメントのみに変更を加えればよいことになります。
データの詳細を保存する場所は、各エレメントのアトリビュート、テキストノード、CDATAに至るまで自由に使うことができます。 userDataの保存ファイルはXMLテキストですが、このXMLDocumentプロパティを使うことで、userDataの能力を100%発揮することができるのです。
このXMLDocumentがとても便利なので、DOM:Storageの方も同じようにDOM操作で保存できるラッパーを作成しました。 今ではIEとFirefoxの両方で同じ使い方が出来る データ保存クラスとして活躍しています。
ヤフーは1月30日、オープンな認証規格「OpenID」の発行サービスをベータ版として開始した。OpenIDを利用すれば外部サイトでもYahoo! JAPAN IDが利用できるようになると同時に、ウェブサービスの開発者はヤフーが抱える2000万ID以上のアクティブユーザーに向けたサービスの開発が可能となる。
予想より早く開始しましたね。 YahooのOpenIDはセキュリティに配慮しているほか、既存OpenIDプロバイダと違う点も見られます。
OpenID対応サイトでログインする際は、「yahoo.co.jp」と 入力するだけでよく、YahooサイトでYahooのIDとパスワードを入力して認証します。 OpenID対応サイトには、「https://me.yahoo.co.jp/a/tsEJe4MCcbXZyYq0VzUTfWemVtG0」のような、YahooのIDを含まないOpenIDが通知される仕組みです。
ということで早速ログインを試みたところ、「このサイトにログインできません。」というエラーが表示されました。 どうもリダイレクト時にreturn_to?のホスト確認をしているらしく、 「localhost」などのテスト環境は弾かれます。 正式なドメインからアクセスすると成功しました。
以下はYahooから返信される情報を一部抜粋したものです。
array ( 'openid_ns' => 'http://specs.openid.net/auth/2.0', 'openid_mode' => 'id_res', 'openid_return_to' => 'http://www.softama.com/openid_test/result.php?janrain_nonce=2008-01-31T02%3A31%3A04ZrWi9Zr', 'openid_claimed_id' => 'https://me.yahoo.co.jp/a/tsEJe4MCcbXZyYq0VzUTfWemVtG0#6c56c', 'openid_identity' => 'https://me.yahoo.co.jp/a/tsEJe4MCcbXZyYq0VzUTfWemVtG0', 'openid_assoc_handle' => 'YPKehsnKyC3deS46Zt4oZQqrkYd3CWVx5b6vGbLq24Nc.lJ0mpXD3D3GOhCURjzvb3VRkIkJgCeqQBUPpht25UJDfslk6QNg4Q0F5qIuCOI04zPYG_BXskrS9aHgmkTYkQ--', 'openid_realm' => 'http://www.softama.com/openid_test/', 'openid_response_nonce' => '2008-01-31T02:31:36Z4vQ0bDrKtR9L4I52M10eFeQceUophyRhaQ--', 'openid_signed' => 'assoc_handle,claimed_id,identity,mode,ns,op_endpoint,response_nonce,return_to,signed', 'openid_op_endpoint' => 'https://open.login.yahooapis.jp/openid/op/auth', 'openid_sig' => 'N6a5hPDj4L36B5jrEgMoZG4luiE=', )
identityはYahooの登録情報ページから参照できるOpenIDと同じです。 ところが、claimed_idには#6c56cのような末尾が付いていました。(#以降がころころ変わるようなら問題ですが、多分大丈夫でしょう。 少し様子を見るつもりです。)
追記: Discover時に取得できるXRDSドキュメントを載せておきます。
<?xml version="1.0" encoding="UTF-8"?>
<xrds:XRDS
xmlns:xrds="xri://$xrds"
xmlns:openid="http://openid.net/xmlns/1.0"
xmlns="xri://$xrd*($v*2.0)">
<XRD>
<Service priority="0">
<Type>http://specs.openid.net/auth/2.0/server</Type>
<URI>https://open.login.yahooapis.jp/openid/op/auth</URI>
</Service>
</XRD>
</xrds:XRDS>
この時点ではclaimed_idが判明していません。 従って、リダイレクト時に要求するclaimed_idとidentityには「http://specs.openid.net/auth/2.0/identifier_select」 を設定しています。
Yahooのような多くのユーザを抱えるサイトがOpenIDを発行することで、これからOpenIDに対応するサイトが増えていくことでしょう。 今後もOpenIDの動向に注目したいと思います。
前回のエントリに続いてOpenIDのテスト話。 以下はテストコードから抜粋したものです。
// Consumerを作成
$store = new Auth_OpenID_FileStore($store_path);
$consumer = new Auth_OpenID_Consumer($store);
// OpenIDの認証プロセスを開始
if (!$req = $consumer->begin($openid))
error_exit("指定されたOpenIDは無効です。");
// OpenIDプロバイダにリダイレクト
$url = $req->redirectURL($trust_root, $return_to);
if (Auth_OpenID::isFailure($url))
error_exit("リダイレクトに失敗しました。");
header("Location: ".$url);
続いて受信フェーズ
// Consumerを作成
$store = new Auth_OpenID_FileStore($store_path);
$consumer = new Auth_OpenID_Consumer($store);
// OpenIDプロバイダからの返信情報
$resp = $consumer->complete($return_to);
if ($resp->status != Auth_OpenID_SUCCESS)
error_exit("認証失敗:".$resp->status);
$openid = $resp->getDisplayIdentifier();
// 結果表示
print_html("result.html", array("msg"=>"認証成功: id=$openid"));
以上。 これで動作しています。
今回テストしてみて、初回のbegin で結構な時間を待たされるのが気になります。(特にWindows環境で顕著。PHPのmax_execution_timeを超えます) 他にもポリシーをどうするかとか、リダイレクトをformで実装する方法などを調べなくては。
余談ですが、openid.ne.jpのサイトはJanRainのserver.phpライブラリで構築されているようです。 (偶然サーバエラーを見かけて、そのファイル名がまさにこのライブラリでした…)
OpenIDの実装をどうするか考えてみる。 仕様に沿って1から全て作るのは時間がもったいない。幸いにも先人たちが作成したライブラリが利用できるので利用することに。
ここに各種言語向けのライブラリが用意されている。
http://wiki.openid.net/Libraries
PHPでOpenID 2.0にも対応しているJanRainのライブラリを選択した。(多言語に展開しているし実績がありそうなので…)
http://www.openidenabled.com/php-openid/
サンプルコードも単純で理解しやすく、完璧ではないがphpDocumentorのドキュメントも用意されている。
今回はServerではなくConsumerを作成するのが目的。流れを理解するのにphpDocのconsumer.phpの説明がとても役に立つ。(OpenIDについてもうまく説明されているので最初からここを見ればよかった)
このライブラリを使った処理の流れ。
前半終了。OpenIDプロバイダから戻り先のURLにリダイレクトしてきたら後半開始。
基本これだけなので簡単だ。 後でテストスクリプトを組んで実験してみよう。
前々から興味のあったOpenIDについて調べてみた。 ユーザとして利用するのはもちろんだが、今回はWebサービス側の情報を収集して、最終的にはテストも兼ねてRSS+リーダーに実装したいと考えている。
http://openid.net/developers/specs/
「OpenID Authentication 2.0 Final」と書かれた資料の日付が2007/12/7 なことから、つい最近2.0の仕様がまとまったことが推測できる。(まだ世の中に2.0は浸透していない?)
仕様書を読んで大雑把に理解した処理の流れ。
Endpoint URLとは、認証プロセスをやり取りするためにOpenIDプロバイダが用意したURL。 ここにコマンドを投げれば結果を返してくれる。 紹介されている要求コマンドはassociate, checkid_immediate, checkid_setup, check_authentication。
checkid_*はブラウザごとリダイレクトするもので、他はhttpのPOSTを投げると直ぐに結果が得られる。(前者はindirect request、後者はdirect requestと書かれている)
取り合えずここまで。