ラベル HTML5 の投稿を表示しています。 すべての投稿を表示
ラベル HTML5 の投稿を表示しています。 すべての投稿を表示

2014年4月14日月曜日

.jpg の MIME Type は image/jpeg

HTML 5 で <input type="file"> の accept 属性に MIME Type を指定すると、特定の種類のファイルだけを受け付けることができます。

.jpg ファイルの場合は image/jpeg となります。
image/jpg と書いてしまうと動かないので要注意です。
<!-- うごく -->
<input type="file" accept="image/jpeg">

<!-- うごかない -->
<input type="file" accept="image/jpg">


参考
MIMEタイプ一覧 | TNK HomePage
http://www.geocities.co.jp/Hollywood/9752/mime.html

2014年2月25日火曜日

HTML5: placeholder で入力例を示す

HTML5 のテキスト入力フォームで、placeholder を指定すると、
以下のように入力例などを指定することができる。
初期値を入力する場合とは異なり、
フォーカスを当てた時や入力を始めた時に消えてくれる。
ただし古いブラウザでは表示されないので注意が必要。

<label>お名前:<input type="text" placeholder="例:田中太郎"></label>

2013年12月19日木曜日

html 要素の lang 属性で言語を指定する

HTML5 の <html> 要素の lang 属性でページの言語を設定できる。
ここで設定した言語は、音声読上げソフトが読み上げ時に
どの言語で読み上げるのかを判断する材料になるため、
基本的には設定したほうが良い。
<!DOCTYPE html>
<html lang="ja">
...
...
</html>

HTML5 仕様書
http://www.w3.org/TR/2013/CR-html5-20130806/semantics.html#the-html-element

2013年9月30日月曜日

HTML5 Audio でマルチブラウザ対応するときの注意

HTML5 の <audio> を使ってマルチブラウザに対応する場合には2種類の音声ファイルを準備する必要があります。
先日の Google 生誕16周年の記事でも書きましたが現状では mp3 と ogg ファイルの準備が必要です。

各ブラウザの Audio 要素の対応フォーマット一覧を見てみると、
Safari, IE は ogg ファイルを、Chorme, Opera, Firefox は mp3 ファイルを再生できません。
これらのブラウザで音声を再生する場合は両方とも設定する必要があります。
http://fmbip.com/litmus/



ブラウザゲームなどを開発する場合は mp3 と ogg 両方とも準備しましょう。
今後はアップデートによって ogg のみ、 mp3 のみでも再生できるようになるとよいですね。

2013年9月13日金曜日

HTML5 でプログレスバーを表示

HTML5 では <progress> タグを使うことで処理の進捗を表示することができます。
<progress value="0" max="100"></progress>

max にゲージの最大値を、 value に現在の値をセットします。
value を更新することでゲージを動かすことができます。

2013年8月22日木曜日

accept 属性でアップロードするファイルフォーマットを指定

HTML5 では <input> タグの type 属性が "file" の場合に、アップロードできるファイルのフォーマットを指定する属性があります。

accept 属性を追加して以下の値をセットします。

  • image/*, video/*, audio/*
  • MIMEタイプ
  • ファイル拡張子

image/*, video/*, audio/* はそれぞれ画像ファイル、動画ファイル、音声ファイルだけを受け入れる値です。MIME タイプは image/png などのように更に具体的な値を設定可能です。ファイル拡張子は ".doc" や ".txt" などの用にファイルの拡張子によって受け入れるかどうかを判断するオプションです。

Mac の Safari, Firefox, Chrome で試してみたのですが、ファイルの拡張子による指定は今のところ、Chrome でしか動いていませんでした。実際には image/*, video/*, audio/* か MIME タイプを使うことになりそうです。

accept が指定されている場合には、アップロードするファイルの選択画面で、フォーマットが合わないファイルは選択不可能になります。もちろん気休め程度なので、サーバ側でのチェックは必須ですが。

指定されたフォーマットだけが選択可能になる


以下にサンプルを作成しました。いくつかのブラウザでお試しください。

ソースコードはこちら(GitHub)

accept 属性の仕様はこちら(W3C)

2013年8月6日火曜日

HTML5 ドラッグ&ドロップ API の drop イベントが発動しない

drop イベントは dargover イベントと dragenter イベントをキャンセルしなければ発動しない仕様になっています。
$('#dropzone').on('drop', function() {
 $(this).html('ドロップされました');
}).on('dragover dragenter', function() {
 // イベントをキャンセル
 return false;
});

サンプルアプリ
http://okanoworld.appspot.com/sample/html5/dnd_dom/index.html

ソースコード
https://github.com/yokano/sample/tree/master/html5/dnd_dom


2013年8月2日金曜日

HTML5 ドラッグAPI 仕様書翻訳後半

翻訳は途中で力尽きました・・・
もう1回ゆっくり読み直さないと詳細は理解できなさそう。

とりあえず大事なのは
- ユーザがドラッグを始めたらブラウザが drag data store にデータを追加する
- drag data store は直接触れない
- drag data store にアクセスするために使うのが dataTransfer インタフェース
- dataTransfer インタフェースは DOM に発行されるドラッグイベントに付加される
- ファイルシステムや他のアプリケーションからドラッグするため、OSに依存して動作が変わる部分がある。(他のキーとの組み合わせが意味する操作とか)

といったところでしょうか。


以下翻訳メモ後半。

原文はこちら
http://www.w3.org/TR/2012/CR-html5-20121217/editing.html#dnd

------



7.7.4 DragEvent インタフェース

ドラッグ&ドロップ処理モデルはいくつかのイベントを呼び出す。それらはすべて DragEvent インタフェースを使う。

[Constructor(DomString type, optional DragEventInit eventInitDict)]
interface DragEvent : MouseEvent {
    readonly attribute DataTransfer? dataTransfer;
};

dictionary DragEventInit : EventInit {
    // Attributes from UIEvent:
    Window? view = null;
    long detail = 0;
    // Attributes for MouseEvent:
    long screenX = 0;
    long screenY = 0;
    long clientX = 0;
    long clientY = 0;
    boolean ctrlKey = false;
    boolean shiftKey = false;
    boolean altKey = false;
    boolean metaKey = false;
    unsigned short button = 0;
    unsigned short buttons = 0;
    EventTarget? relatedTarget = null;
    // Attributes for DragEvent:
    DataTransfer? dataTransfer;
};

 以下は非標準
----
event.dataTransfer:DataTransferオブジェクトを返す
----

DragEvent の dataTransfer は初期化された値を返さなければならない。オブジェクトが作られた時、この属性は null に初期化されなければならない。これはイベントにコンテキストを知らせるためにある。

ユーザエージェントが e という名前のドラッグアンドドロップイベントをエレメント上で実行することを要求した時、以下の手順で drag data store を使用しなければならない。

1. e が dragstart だったら drag data store mode を read/write モードにする
   e が drop だったら drag data store mode を red-only モードにする
2. dataTransfer に新しく作られた drag data store と関連づいた DataTransfer を代入する。
3. effectAllowed に drag data store の drag data store allowed effects state を代入する
4. e が dragstart, drag, dragleave のいずれかだったら dropEffect に "none" を代入する。e が drop または dragend だったらcurrent drag operation と同じ値を代入する。その他は effectAllowed に基づいた値と drag-and-drop ソースによって、以下の表から与えられる値になる。

effectAllowed    | dropEffect
"none"           | "none"
"copy"           | "copy"
"copyLink"       | "copy" または "link"
"copyMove"       | "copy" または "move"
"all"            | "copy" または "link" または "move"
"link"           | "link"
"linkMove"       | "link" または "move"
"move"           | "move"
"uninitialized"  | "move" または "copy" または "link"
 textfield 選択中|
"uninitialized"  | "copy" か "link" か "move"
 ドラッグ中      |
"uninitialized"  | "link" か "copy" か "move"
 a要素を選択中   | "link" か "copy" か "move"
それ以外のケース | "copy" か "link" か "move"

上の表以外で、ユーザエージェントのプラットフォームの慣習的なものがあれば、ユーザエージェントはそちらの操作をするかもしれない。

例えば、Windows の慣習では "alt" キーを押しながらドラッグしている間は、移動やコピーよりも、データをリンクさせることを意味する。従って、Windows では "alt" キーが押されている間は "copy" や "move" ではなく "link" となる。

5. 信頼された DragEvent を作成して e として初期化する。バブリングするか、キャンセル可能でない限り、 e は dragleave か dragend であり、detail 属性を 0 で初期化する。mouse と key 属性はユーザインタラクションを行う入力デバイスの状態によって初期化する。relatedTarget 属性は null で初期化する。dataTransfer 属性は DataTransfer 変数によって初期化する。DataTransfer オブジェクトは上で作成されている。
6. target 要素の DragEvent を通知する
7. drag data store allowed effects state に dataTransfer の effectAllowed 属性をセットする。(e が dragstart の場合だけ変更できる)
8. drag data store mode を最初のステップで変更していたら protected モードの戻す。
9. dataTransfer と drag data store の関係を切る


7.7.5 ドラッグ&ドロップ処理モデル

ユーザがドラッグを開始した時、ユーザエージェントは下記のステップを処理しなければならない。以下のステップを実行するときには、ドラッグ開始地点が他のドキュメントやアプリケーションであり、どこでドラッグを開始されたのかを知ることができない場合であっても、実行しなくてはならない。

1. 以下の手順で何がドラッグされたのかを突き止める
    選択によってドラッグが開始されたのであれば、選択から開始された。
    そうではなく、Document からドラッグが開始されたのであれば、それはdraggable 属性が設定されているノードから先祖へと向かって参照していった先の、最初の要素である。draggable に設定された要素がなければ何もドラッグされていないため、以下のステップを中止してドラッグ&ドロップ操作は行わない。
 それ以外はユーザエージェントの外側からのドラッグである。何がドラッグされたのかはドラッグが開始されたドキュメントやアプリケーションによって定義される。

 ノート:href属性を持っているimg要素とa要素はデフォルトでdraggable属性にtureを設定している。

2. drag data store を作成する。すべてのドラッグ&ドロップイベントはこのセクションのステップの後に続いて発行され、drag data store を使わなければならない。

3. 以下の手順でどの DOM ノードがソースノードなのかを確証する。
    ドラッグされたのが選択範囲なら、ユーザがドラッグを開始した Text ノードがソースノードである。ユーザがユーザエージェントに具体的なノードを通知していない場合は、ドラッグされた選択領域を含んでいる Text ノードがソースノードである。
    それ以外で、DOM要素がドラッグされていたら、ソースノードはその要素である。
    それ以外なら、ソースノードは他のドキュメントやアプリケーションの一部である。この仕様が、イベントがソースノードから発行されることを要求するとき、ユーザエージェントはプラットフォームの慣習やシチュエーションに合わせて適切なソースノードを決めなければならない。
 ノート:ドラッグ&ドロップ中はソースノードから複数のイベントが発行される。

4. 以下の手順でドラッグされたノード一覧を確定する
    選択領域がドラッグされた場合は、ドラッグされたノード一覧は、選択領域の中に部分的に、または完全に含まれているノードの木構造である。(選択領域のすべての先祖を返す)
    それ以外ならドラッグされたノード一覧はソースノードだけを含む。

5. 選択領域がドラッグされたのなら、drag data store item list に以下のプロパティをもつ要素を追加する。
    The drag data item type string: "text/plain"
    The drag data item kind: Unicode 文字列
    The actual data: 選択した文字列

    それ以外で、ファイルがドラッグされた場合は、drag data store item list に各ファイルの情報を元にしたプロパティを持つ要素を追加する。
    The drag data item type string: ファイルの MIME type か "application/octet-stream"
    The drag data item kind: File
    The actual data: ファイルの中身と名前
    ノート: 現在ではファイルはブラウザの外からしかドラッグできない

    ドラッグがアプリケーションの外で始まった場合、ドラッグされたデータに相応しい(プラットフォームの慣習にあった)データを drag data store item list に追加しなければならない。プラットフォームが MIME types を使っていなかったとしても、ユーザエージェントは最も適切な MIME type を割り当てるよう試みなければならない。そして、すべてのケースで、drag data item type は ASCII コードの小文字でなければならない。

6. ドラッグアンドドロップ初期化ステップは他の使用で定義される。

7. 以下のサブステップを実行する

    1. urls に絶対URL のカラリストを入れる
    2. ドラッグされたノード一覧の各ノードに対して
        ノードが href 属性付きの a 要素なら、href をリゾルブした URL を urls に追加する
        ノードが src 属性付きの img 要素なら、src をリゾルブした URL をノードに追加する
    3. urls が空のままなら、以下のステップは中止する
    4. url にurls を改行で区切って連結した文字列を代入する。
    5. drag data store item list に以下の手順にそってアイテムを追加する
        type: text/uri-list
        kind: Unicode文字列
        data: url文字列

8. ユーザエージェントに合わせて適切な drag datastore store default feedback を更新する。

9. dragstart という名前でソースノードのドラッグ&ドロップイベントを実行する
    イベントがキャンセルされたら、ドラッグ&ドロップイベントは発生せず、以下のステップを中止する。
    メモ:イベントリスナ無しのイベントは、ほとんどの定義で、永遠にキャンセルされず、作者が意図して防がない限りユーザのためにドラッグ&イベントは利用可能である。

10. 以下で説明しているようにして、プラットフォームの慣習に合わせてドラッグアンドロップを始める
    ドラッグ&ドロップフィードバックは以下の利用可能なソースによって生成されなければならない。
    1. drag data store bitmap。このケースでは、drag data store hot spot coordinate がカーソルの位置を表すために使われなくてはならない。この値は CSS のleft と top として表現される。
    2. drag data store default feedback

ユーザエージェントがドラッグ&ドロップ処理を開始する瞬間から操作が終了するまで、デバイスのインプットイベント(マウスやキーボードイベント)は制限しなくてはならない。

ドラッグ操作中、immediate user selection と呼ばれるドロップターゲットがユーザによってエレメントへ直接指定される。(エレメントはユーザによってだけ選択されることができる。他のノードはドロップターゲットとして利用可能であってはならない)。しかしながら immediate user selection は current target element である必要はない。これはドラッグ&ドロップ操作の中の一部である現在選択中のエレメントのことである。

immediate user selection はユーザが選択した別の要素として変更される(ポインティングデバイスで選択肢たり、他の方法を使う)。current target element は immediate user selection が変化した時に変化する。下記で説明する通り、ドキュメント内のイベントリスナの結果に基づく。

current target element も immediate user selection も null をとることができる。これはターゲットエレメントが選択されていないことを意味する。これらは別のドキュメントのエレメントをとることもできるし、他の(Webではない)プログラムのものでもよい。(例えばワードプロセッサから選択してきたテキストでも良い)。current target element は null で初期化される。

さらに、 current drag operation もあり、"none", "copy", "link", "move" を値として持つことができる。初期状態では "none" を持つ。これは下記の手順によってユーザエージェントが更新できる。

ユーザエージェントはドラッグ操作が始まったらすぐに初期化して、 350ms(±200ms) 毎にその後はドラッグ操作中以下のステップをタスクキューに追加し続けなければならない。

1. ユーザエージェントがまだ以前の処理を指定たら、次の処理が来た時、これらの処理を中断する。(フレームを飛ばす)
2. drag という名前のイベントをソースノードに対して実行する。このイベントがキャンセルされたら、 current drag operation を "none" にしなければならない。(ドラッグ操作は行われない)
3. drag イベントがキャンセルされておらず、ユーザのドラッグ&ドロップ操作が終わっていなければ、ドラッグ&ドロップ操作の状態を以下のステップでチェックする。
    1. もしユーザが最後の処理よりも後で immediate user selection を変更し、それが current target element と同じではなかったら、current target element を以下の手順でアップデートする。
        * 新しい immediate user selection が null だったら、current target element も null にする。
        * 新しい immediate user selection が DOM ドキュメントかアプリケーションだったら、 current target element に immediate user selection を代入する
        * それ以外だったら dragenter イベントを immediate user selection に対して発行する。
          イベントがキャンセルされたら、current target element を immediate user selection にする。
          それ以外なら、以下のリストから適切な処理を実行する。
          - immediate user selection がテキストフィールド(例えばテキストエリやinput要素)または、editing host , editable 要素で、なおかつ drag data store item list が type = "text/plain" で kind が Unicode 文字列の要素を持っていたら、current target element を immediate user selection にセットする。
          - immediate user selection が drop zone 属性を持っていて、 drag data store とマッチするなら、current target element を immediate user selection にセットする。
          - immediate user selection が drop zone の先祖の要素であり、drag data store にマッチするなら、new target に直近の先祖エレメントを代入する。
            もし、immediate user selection が new target だったら、current target element を変化させない。
            それ以外なら、dragenter という名前のドラッグイベントを new target に対して発行する。current target element を new target にする。
          - immediate user selection が body 要素だったら、current target element はそのままにする。
          - それ以外なら、もし1つ以上のDocument オブジェクトが存在したら、dragenter イベントを body 要素に対して発行する。current target を body 要素にする。イベントがキャンセルされたかどうかは気にしない。
    2. もし上のステップで current target element が変更されていて、なおかつ target element が null または DOM ドキュメントの一部なら gragleave イベントを直前の target element に対して発行する。
    3. current target element が DOM なら、 dragover イベントを current target element に発行する。
       dragover イベントがキャンセルされていなかったら、以下のリストから適切なものを実行する。
            * current target element がテキストフィールド、editing host または editable 要素であり、drag data store item list の中に type が "text/plain"、kind がUnicode のアイテムがあったら、current drag operation を "copy" か "move" のどちらか適切な方にセットする。
            * current target element が drop zone 属性を持つエレメントであり、 drag data store にマッチして、具体的な操作を持っていたら、 current drag operation を current target element の drop zone 属性にする。
            * current target element が drop zone 属性を持っていて、drag data store にマッチして、具体的な操作を持っていなければ、 current drag operation に "copy" をセットする。
            * それ以外なら、current drag operation を"none" にする。

        それ以外(dragover イベントがキャンセルされた)なら、DragEvent オブジェクトの dataTransferオブジェクトの effectAllow と dropEffect属性に基づく値を current drag operation にセットする。イベント終了後に下の表のように鳴る。

                                 effectAllowed                         | dropEffect | Drag operation
"uninitialized", "copy", "copyLink", "copyMove", "all"  | "copy"      | "copy"
"uninitialized", "link", "copyLInk" , "linkMove", "all"     | "link"        | "link"
"uninitialized", "move", "copyMove", "linkMove", "all" |  "move"    | "move"
それ以外                                                                                  | "none"

    4. それ以外なら、current target element が DOM 要素ではない場合、プラットフォームの具体的なメカニズムをドラッグオペレーションの判断のために使う。(none, copy, link, move)そして、current drag operation にそれをセットする。

    5. ドラッグフィードバック(例えばマウスカーソル)を current drag operation に合わせて以下のように更新する。
Drag operation | Feedback
"copy"             | ドロップしたらデータがコピーされる
"link"               | ドロップしたらデータがリンクされる
"move"            | ドロップしたらデータが移動される
"none"             | 操作はなく、ドロップするとドラッグアンドドロップがキャンセルされる

4. それ以外で、ユーザがドラッグ&ドロップ操作を終了した(例えばマウスボタンを離した)、または drag イベントがキャンセルされたら、これが最後の処理に鳴る。以下の手順で処理をして、ドラッグ&ドロップ操作を終了する。
    1. current drag operation が "none" だった、または、ユーザがドラッグ&ドロップ操作をキャンセルした(例えば escape キーを押した)、または、current target element がnull だったら、ドラッグ操作は失敗する。以下のサブステップを実行する。
        1. dropped を false にする。
        2. current target element が DOM 要素だったら、dragleave イベントをその要素に発行する。そうではなく、current target element が null だったら、ドラッグをキャンセルするためにプラットフォームの慣習を使用する。
      それ以外だったら、ドラッグ操作は成功する。以下のサブステップを実行する。
       1. dropped を true にする
       2. current target element が DOM 要素だったら、drop イベントを current target element に発行する。それ以外なら、dropを指定するためにプラットフォームの慣習を使用する。
       3. イベントがキャンセルされたら、current drag operation に DragEvent オブジェクトの dataTransfer オブジェクト dropEffect 属性に基づく値をイベントが終了した後にセットする。
          それ以外なら、イベントはキャンセルされない。以下のようにしてデフォルトの動作を実行する。
          - もし current target element がテキストフィールド、 editing host 、 editable 要素のいずれかであり、かつ、typeが"text/plain"、kind が Unicode 文字列のアイテムが drag data store item list 内に存在していたら、実際のデータを drag data store item list の中に挿入する。その時、type を "text/plain"、kindをUnicode文字列、以下略。
         - それ以外、current drag operation を "none" にする。
    2. dragend イベントをソースノードに対して発行する
    3. デフォルトの dragend イベントの動作として以下のリストの中から適切なものを実行する 

2013年8月1日木曜日

HTML5 ドラッグ&ドロップ仕様書翻訳メモ

W3Cの HTML5 Drag And Drop API の仕様書を解読中です。
まだ途中ですがメモ。

原文はこちら
http://www.w3.org/TR/2012/CR-html5-20121217/editing.html#dnd


以下翻訳。


7.7 ドラッグ&ドロップ


このセクションではイベント駆動のドラッグ&ドラッグ機構について定義する。

この仕様は具体的にドラッグアンドロップを動かす具体的な仕組みについては述べない。

ポインティングデバイスによる視覚的な伝達手段では、ドラッグ操作はデフォルトの mousedown イベント、それに続くいくつかの mousemove イベント、そしてマウスが離されることでドロップをトリガーできる。

ポインティングデバイス以外の入力方式を使うとき、ユーザは自分の意図する目的のために、何をドラッグしたいのか、どこにドロップしたいのかを明確に示さなければならないだろう。

どのような方法でも、ドラッグ&ドロップ操作には開始座標が必要(マウスがどこでクリックされたのか、ドラッグのために選択された要素の開始セクションなど)、もしかしたらいくつかの中間ステップを持つかもしれない(エレメントがドラッグ中にマウスを動かされた場合、ユーザがドロップ可能な座標にエレメントを持ってきた時など)、そして必ず終了座標も持つ(上記のエレメントからマウスボタンが離された、エレメントの選択が確定した)、またはキャンセルされる場合もある。終了座標は最後に選択されたドロップ可能要素の座標でなければならない(もし操作がキャンセルされなかったら、中間ステップで使用したエレメントでなければならない)。


7.7.1 導入

このセクションは標準的ではない。

ドラッグ可能要素を作るのは簡単:要素に draggable 属性を与える、そしてドラッグされているデータを保存する dragstart イベントリスナをセットする。

イベントハンドラは一般的に、テキストドラッグがテキスト選択ではないことをチェックする必要がある。そして DataTransfer オブジェクトにデータを保存する必要があり、許可されたエフェクトを追加する(コピー、移動、リンク、またはそれらの組み合わせ)。


<p>好きなフルーツはなんですか?</p>
<ol ondragstart="dragStartHandler(event)">
  <li draggable="true" data-value="fruit-apple">りんご</li>
  <li draggable="true" data-value="fruit-orange">みかん</li>
  <li draggable="true" data-value="fruit-pear">なし</li>
</ol>
<script>
  var internalDNDType = 'text/x-example'; // あなたのサイトに合わせて書き換える
  function dragStartHandler(event) {
    if (event.target instanceof HTMLLIElement) {
      // 移動させるデータとして要素の data-value="" 属性を使う
      event.dataTransfer.setData(internalDNDType, event.target.dataset.value);
      event.dataTransfer.effectAllowed = 'move'; // move を許可する
    } else {
      event.preventDefault(); // LI要素以外はドラッグさせない
    }
  }
</script>

ドロップを受け入れるためには、ドロップ対象は dropzone 属性を持ち、drop イベントを監視する。

dropzone 属性の値は受け入れるデータの種類("string:text/plain"であらゆるテキストを受け入れる、または"file:image/png"でPNG画像ファイルを受け入れるなど)、フィードバックの種類(move だとデータが移動される)を指定する。

 メモ:dropzone属性を使う代わりに、dragenterイベント(ドロップをアクセプトするかどうかを判断する)とdragoverイベント(ユーザに何をフィードバックするのか)を使える。

drop イベントは現在のドロップを受け入れる。このイベントはキャンセルされることが必要、dropEffect はsource が使うことができる。(またはリセットされる)


<p>一番好きな果物をドロップしてね</p>
<ol dropzone="move string:text/x-example" ondrop="dropHandler(event)">
  <!-- "text/x-example"を自分のサイトに合わせて変えるのを忘れないように -->
  <script>
    var internalDNDType = 'text/x-example'; // 自分のサイトに合わせて書き換える
    function dropHandler(event) {
      var li = document.createElement('li');
      var data = event.dataTransfer.getData(internalDNDType);
      if (data == 'fruit-apple') {
        li.textContent = 'りんご';
      } else if (data == 'fruit-orange') {
        li.textContent = 'みかん';
      } else {
        li.textContent = '知らない果物';
      }
      event.target.appendChild(li);
    }
  </script>
</ol>

ドラッグされた元々の要素を画面から削除するために、 dragend イベントを使う。

元々のマークアップをアップデートしてイベント処理をしている。

<p>好きな果物は?</p>
<ol ondragstart="dragStarthandler(event)" ondragend="dragEndHandler(event)">
  ..上のコード...
</ol>
<script>
  function dragStarthandler(event) {
    // …上のコード...
  }
  function dragEndHandler(event) {
    // …上のコード…
    event.target.parentNode.removeChild(event.target);
  }
</script>


7.7.2 ドラッグデータの保存

ドラッグ&ドロップ操作の基礎にあるデータは、drag data storeとして知られていて、以下の情報から成り立っている。

◯drag data item listはドラッグされたデータのリストで、それぞれ以下の情報から成り立っている。
   - drag data item kind:データの種類
     - Plain Unicode string:テキスト
     - File:ファイル名とバイナリデータ
   - drag data item type string:一般的には MIME type でデータタイプかフォーマットを与える。MIME  type が与えられない場合は過去の名残などの理由がある。API は MIME types を使うことを強要しない。他の値でも動く。すべてのケースにおいて、すべての値は API によって ASCII コードの変換される。

 メモ:dropzone属性にスペースを含む文字列は使えない、MIME types か空白を含まない文字列を使うことが推奨される。

 item type は Unicode 文字列であることが条件。

 実際のデータ:drag data item kind 毎に、バイナリデータとファイルネーム(Unicode)を持つ。

 drag data store item list はリストにアイテムが追加されたらソートされる。

◯ドラッグ次のUIフィードバックに以下の情報が使われる
   - ユーザエージェントは デフォルトフィードバックとして、drag data store default feed back を持つ。
   - オプションで、drag data store bitmap と drag data store hot spot coordinate としてビットマップ画像と座標の組を持てる

◯drag data store mode は以下のいずれかをとる。
 - Read/write mode:dragstart イベント用。新しいデータは drag data store に追加できる。
 - Read-only mode:drop  イベント用。ドラッグデータとして表現されるアイテムリストを読める。新しいデータの追加はできない。
 - Protected mode:その他のイベント用。ドラッグデータとして表現される drag data store のフォーマットと種類を数えることができるが、読み込んだり追加したりすることはできない。

◯drag data store allowed effects state という文字列。


drag data store が作られた時、上記のデータは以下のように初期化されなければならない。drag data store item list は空、drag data store default feedback は存在しない、drag data store bitmap と drag data store hot spot coordinate を持たない、drag data store mode は protected mode、drag data store allowed effects state は "uninitialized"になる。


7.7.3 DataTransfer インタフェース

DataTransfer オブジェクトはドラッグ&ドロップ操作の根底に隠れている drag data sotre を表に出すために使われる。

interface DataTransfer {
                 attribute DOMString dropEffect;
                 attribute DOMString effectAllowed;
    readonly attribute DataTransferItemList items;
    void setDragImage(Element image, long x, long y);
};

以下は非標準。実装についての要求。

---
dataTransfer.dropEffect
    現在選択されている操作の種類を返す。もし effectAllowed で許可されていない種類だった場合は操作は失敗する。選択している操作を変更するために、この値を設定できる。可能な値は "none", "copy", "link", "move"のいずれか。

dataTransfer.effectAllowed
 許可する操作の種類を返す。許可する操作を変更するためにセットすることができる(dragstartイベントの間だけ)。設定できる値は "none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", "uninitialized"のいずれか。

dataTransfer.items
 ドラッグデータと一緒に DaraTransferItemList を返す。

dataTransfer.setDragImage(element, x, y)
 ドラッグフィードバックをアップデートして、以前のフィードバックと置き換えるために使う。

dataTransfer.types
 dragstart イベントでセットしたフォーマットのリストを返す。また、もしいくつかのファイルがドラッグされていたら、types の1つは "Files" になる。

data = dataTransfer.getData(format)
 具体的なデータを返す。データなかったら空文字列を返す。

dataTransfer.setData(format, data)
 具体的なデータを追加する

dataTransfer.clearData([format])
 format で設定されているデータを削除する。引数がない場合はすべてのデータを削除する。

dataTransfer.files
 ドラッグされている FileList があれば返す。
---

DataTransfer オブジェクトはドラッグ&ドロップイベントの間使われる。そしてドラッグ&ドロップイベントが発生している間は有効である。

DataTransfer オブジェクトは drag data store と関連している。

dropEffect 属性はユーザがドラッグ&ドロップ操作をしている間のフィードバックを制御する。DataTransferオブジェクトが作成された時、dropEffect 属性として文字列の値がセットされる。取得するとき、必ず現在の値を返さなければならない。セットするとき、新しい値が "none", "copy", "link", "move"のいずれかだったら、 dropEffect属性は新しい値に変更されなければならない。その他の値は無視されなければならない。

effectAllowed 属性は dragenter イベントと dragoverイベントの間、 dropEffect属性を初期化するためにドラッグ&ドロップ処理モデルによって使われる。DragTransferオブジェクトが作成された時、effectAllowed属性は文字列で初期化される。取得するとき、必ず現在の値を返す。セットするとき、もじ drag data sotre の mode が read/write であり、 "none", "copy", "copyLink", "copyMove", "link", "linkMove", "move", "all", "uninitialized" だったら新しい値に書き換える。その他だったら変更しない。

items 属性は DataTransfer オブジェクトに関連付いた DataTransferItemList オブジェクトを返さなければならない。どんな時でも同じデータを返さなければならない。

setDragImage(element, x, y) メソッドは必ず以下のステップで実行されること。

1. もし DataTransfer オブジェクトが drag data store と今後関連づかないなら、以下のステップはやらなず、何も起きない。
2. もし drag data store の mode が read/write mode だったら、以下のステップをやらず、何も起きない。
3. もし element 引数が img 要素だったら、 drag data store bitmap に要素の画像をセットする。そうじゃなければ drag data store bitmap に、与えられた要素から画像を生成してセットする。(具体的なsより方法についてはここでは述べない)
4.  drag data store hot spot coordinate に、与えられた x, y をセットする。

type 属性は live read only 配列を以下のステップで返さなければならない。同じオブジェクトはいつでも必ず同じ値を返す。

1. 空の配列 L から始める
2. DataTransfer オブ絵jクトが今後 drag data store と関連づかないなら、配列は空とする。以下のステップをやらずに、空の配列 L を返す。
3. drag data store item list の各要素の kind (Unicode文字列)について、 L に追加する。
4. drag data store item list の中に kind が File のアイテムがあったら、L に "Files" を追加する。
5. これらのステップによって生成された文字列が L に入る。

getData(format) メソッドは以下のステップで実行されなければならない

1. DataTransfer オブジェクトが今後 drag data store と関連づかないなら、空文字を返して以下のステップはやらない。
2. drag data store の mode が protected だったら、空文字を返して何もしない。
3. fomart に最初の引数を小文字に変換したものを代入
4. convert-to-URL に false を代入
5. format が "text" だったら、"text/plain" に変更
6. format が "url" だったら、"text/uri-list" に変更して convert-to-URL を true にする
7. drag data store item list に kind が Unicode 文字列かつ type string が format と同じアイテムがなければ、空文字を返して以下のステップを中止する。
8. result に drag data store item list 内の kind が Unicode 文字列で type string が format と同じアイテムを代入する。
9. convert-to-URL が true だったら、text/uri-list にあった形式にパースして、result にセットする。
10. result を返す

setData(format, data) は以下のステップで実行されなければならない

1. DataTransfer オブジェクトが drag data store に関連づかないなら何もしない。
2. drag data store の model が read/write mode でなければ、何もしない。
3. format に最初の引数の format を小文字に変換して代入する
4. formart が text だったら text/plain に変更する。format が url だったら text/uri-list に変更する。
5. drag data store item list から、 kind が Unicode でtype string が format のアイテムを削除する。
6. drag data store item list に kind が Unicode で type string が format、data が第2引数に渡された文字列をセットする。

clearData() は以下のステップで実行されなければならない

1. DataTransfer オブジェクトが drag data store と以後関連づかないなら、何もしない。
2. drag data store の mode が read/write じゃなかったら、何もしない。
3. メソッドが引数なしで呼ばれたら、drag store item list 内で kind が Unicode の要素を削除して、以後のステップをやらない。
4. format に第一引数を小文字にした文字列を代入する
5. format が text だったら text/plain にする。 url だったら text/uri-list にする。
6. kind が Unicode で、type が format と同じアイテムを drag data store item list から削除する。

メモ:clearData() メソッドはドラッグにファイルが挿入されているかどうかに影響されない。clearData() が呼ばれて types 属性リストが空だったとしても影響されない。

files 属性は File オブジェクトを含む live FireList 配列を以下のステップによって表現して返す。同じオブジェクトはいつでも同じ値を返す。

1. 空の配列 L から始める
2. DataTransfer オブジェクトが drag data store と以後関連づかないなら、FileList を空にして以下のステップをやらない。空のリスト L を返す。
3. drag data store の mode が protected mode だったら、以下のステップをやらずに空のリスト L を返す。
4. drag data store item list の kind が File のアイテムに対して、L にアイテムのデータ(ファイルとファイル名)を追加する。
5. 以上のステップで見つかったのもを L とする。

 メモ:このバージョンの API はドラッグ中の types を表には出さない。


7.7.3.1 DataTransferItemList インタフェース

各 DataTransfer オブジェクトは DataTransferItemList に関連づいている。

interface DataTransferItemList {
    readonly attribute unsigned long length;
    getter DataTransferItem (unsigned long index);
    deleter void (unsigned long index);
    void clear();

    DataTransferItem? add(DOMString data, DOMString type);
    DataTransferItem? add(File data);
}

以下は非標準。実装について。
----
items.length
    drag data store の要素数を返す

items[index]
    指定された位置にある DataTransferItem オブジェクトを返す

delete items[index]
    指定された位置のアイテムを削除する

items.clear()
    drag data store のすべてのアイテムを削除

items.add(data)
items.add(data, type)
 引数として受け取ったデータを drag data store に追加する。もし data がプレーンテキストだったら type も与えられているべきである。

DataTransferItemList の DataTransfer オブジェクトは drag data store に関連づいている、DataTransferItemList オブジェクトの mode は drag data store mode と同じ。DataTransferItemList オブジェクトのDataTransfer オブジェクトがdrag data store と関連づいていないバア愛、DataTransferItemList オブジェクトの mode は disabled になる。このセクションで参照されるdrag data store は DataTransferItemList オブジェクトの DataTransfer オブジェクトと関連づいている。

length 属性は disabled のとき必ず 0 を返さなければならない。それ以外は drag data store item list の長さを返す。

DataTransferItemList が disabled モードではないとき、 0 から n - 1 までの間の値をとる。n は drag data store item list の長さ。

DataTransferItemList オブジェクトのインデックス i を決めるために、ユーザエージェントは drag data store の i 番目として表現される DataTransferItem オブジェクトを返さなければならない。DataTransferItemList オブジェクトから取得してきた要素は、同じものならどんなときでも必ず同じ値を返さなければならない。DataTransferItem オブジェクトは DataTransferItemList オブジェクトのように、初期化時に同じDataTransferオブジェクトから関連付けられる。

i としてインデックスされた DataTransferItemList のプロパティを削除するために、ユーザエージェントは以下のステップで実行しなければならない。

1. DataTransferItemList が read/write モードではなかったら、InvalidStateError 例外をスローして以下のステップを中止する。
2. drag data store の i番目のデータを削除する

DataTransferItemList が read/write モードだったら clear() メソッドは drag data store のすべての要素を削除しなければならない。それ以外は何もしてはいけない。

add() メソッドは以下の手順に従わなければならない。

1. DataTransferItemList が read/write モードではなかったら、nullを返して以下のステップを中止する。
2. 以下のリストから適切なステップにジャンプする
    → 第一引数が文字列
        drag data store item list 内に kind が Unicode で type がメソッドの第二引数と同じ物があれば、NotSupportedError 例外をスローして以下のステップを中断する。
        それ以外なら、drag data store item list に kind が Unicode で type がメソッドの第二引数であり、データがメソッドの第一引数の文字列であるアイテムを追加する。
    → 第一引数が File
        kind が FIle で type が File のファイルタイプでデータが引数として渡された File であるアイテムを drag data store item list に追加する。
3. 新しく追加されたアイテムの index プロパティとその値(新しく作られた DataTransferItem)を返す。


7.7.3.2 DataTransferItem インタフェース

各 DataTransferItem は DataTransfer に関連している。

interface DataTransferItem {
    readonly attribute DOMString kind;
    readonly attribute DOMString type;
    void getAsString(FunctionStringCallback? _callback);
    File? getAsFile();
};

[Callback, NoInterfaceObject]
interface FunctionStringCallback {
    void handleEvent(DOMString data);
}

以下は非標準
---
item.kind
    drag data item kind を返す。"string" か "file"。
item.type
    drag data item type を返す。
item.getAsString(callback)
    drag data item kind の文字列を引数として callback を呼び出す
file = item.getAsFile()
    アイテムの kind が File だったら File を返す
---

DataTansferItem と DataTransfer は drag data store と drag data store item list に関連づいていて、DataTransferItem を内部に持っている。DataTransferItem の mode はdrag data store mode と同じものである。DataTransferItem の DataTransfer が drag data store と関連づいていない、または DataTransfer が関連した drag data store item list から削除されていた場合、DataTransferItem の mode は disabled になる。このセクションで言う drag data store はDataTransferItem の DataTransfer オブジェクトに関連した drag data store である。

DataTransferItem が disable モードなら kind は空文字を返さなくてはならない。それ以外なら以下の表に合わせた値を撮らなくてはならない。

          Kind              | String
Plain Unicode string | "string"
File                         | "file"

DataTransferItem が disable なら type は空文字を返さなくてはならない。それ以外なら DataTransferItem の drag data item type string を返さなくてはならない。

getAsString(callback) は以下の手順で動かなくてはならない。

1. callback が null なら以下の手順を中止する
2. DataTransferItem が read/write モードまたは read-only mode ではなかったら以下の手順を中止して、callback は呼ばない。
3. drag data item kind が Unicode 文字列じゃなかったら以下の手順を中止して callback は呼ばない。
4. それ以外なら、callback をタスクキューに追加する。DataTransferItem として表現される実際のデータを渡して callback を呼び出す。

getAsFile() は以下のように動作しなければならない

1. DataTransferItem が read/write または read-only ではなかったら null を返して以下のステップを中止
2. drag data item kind は File ではなかったら、 null を返して以下のステップを中止
3. DataTransferItem として表現される File を返す

2013年7月23日火曜日

HTML5 ドラッグ&ドロップでファイルをアップロード

---
プログラム修正しました (2014/03/30)
ご報告ありがとうございました
---

HTML5 のドラッグ&ドロップ API  と jQuery.ajax() を使って、
ブラウザ上にドラッグ&ドロップしたファイルをサーバへアップロードする方法です。

ソースは GitHub へ上げました。
https://github.com/yokano/dnd_file_upload

以下の流れで実現出来ます。
  1. dropzone にファイルがドロップされる
  2. drop イベントが発生する
  3. イベントオブジェクトの dataTransfer からファイルを取得する
  4. FormData を作成してファイルを追加する
  5. Ajax でファイルを送信する
HTML
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>ドラッグ&ドロップでファイルアップロード</title>
  <link rel="stylesheet" href="dnd.css">
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script src="dnd.js"></script>
 </head>
 <body>
  <h1>画像ファイルのアップロード</h1>
  <div id="dropzone" dropzone>
   ここへ画像ファイルをドロップ
  </div>
 </body>
</html>

JavaScript
$(function() {
 $('#dropzone').on('drop', function(event) {
  var file = event.originalEvent.dataTransfer.files[0];
  var formData = new FormData();
  formData.append('file', file);
  
  $.ajax('./upload.php', {
   method: 'POST',
   contentType: false,
   processData: false,
   data:formData,
   error: function(xhr, error) {
    console.log('アップデートに失敗しました');
    console.log(error);
   },
   success: function(response) {
    console.log('アップロードに成功しました');
    console.log(response);
    
    
   }
  });

  return false;
    
 }).on('dragover', function(event) {
  return false;
 });
});
PHP
<?php

if(is_uploaded_file($_FILES['file']['tmp_name'])) {
 move_uploaded_file($_FILES['file']['tmp_name'], './' . $_FILES['file']['name']);
}

?>

サーバから見た場合、以下の <form> からファイルがアップロードされた時と、
全く同じデータがクライアントから渡されます。
formData.append('file', file) の 'file' が <input> タグの name 属性に対応します。
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file"></file>
</form>

ドラッグ&ドロップについてはこちら
Drag and drop - W3C

FormData についてはこちら
The FormData Interface - W3C

jQuery.ajax() についてはこちら
jQuery.ajax() - jQuery

2013年4月16日火曜日

もぐらたたき for 3DS を公開

もぐらたたき for 3DS を公開しました。
Nintendo 3DS のウェブブラウザ上で動作するブラウザゲームです。
3DS 以外の PC やスマートフォンのブラウザでも動作します。

アプリ本体
http://okanoworld.appspot.com/mogura

ソースコード
http://yokano.github.io/mogura/


3DS のウェブブラウザで遊べます

ゲームエンジンとして enchant.js を使用しています。
3DS 上では思っていたよりもパフォーマンスが出せず、
9箇所の穴から9つのもぐらのスプライトを出すだけで処理落ちが発生しています。
フレームの処理が遅いため、fps を 30 などにするとスローモーション状態です。
結局、fps を 5 に設定しています。
タッチイベントを ontouchstart で取得していますが、こちらも 0.5 秒近くラグがあります。


9つの穴からもぐらが出現

ランキングにも対応しており、上位 10 までをランキング画面で確認できます。
サーバを Google App Engine + Go でつくり、Ajax で名前とスコアを送信しています。
Ajax は問題なく動作しました。GAE の Channel API による Ajax ポーリングが処理できるか試してみたいですね。


ランキングに登録

ランキング画面

実行中に「画像の表示に失敗しました」や「スクリプトの実行を停止します」と表示され、実行が止まることがあります。
コンソールがないため原因がわからないのですが、表示される場合とされない場合があります。
メモリの使い過ぎかと思い、画像を jpg にして容量を抑えたりしましたが変わりませんでした。
その他の Web サイトをサーフィンしていても発生します。
3DS の Web ブラウザは、アクションゲームや画像の多いゲームは厳しいことがわかりました。

次回は 3DS のブラウザで遊べるソーシャルゲームを作ってみようと思っていますが、上記の問題で厳しければ、また別のものを考えます。

2013年2月11日月曜日

Canvasでline-heightは無視される

HTML5 の Canvas では行の高さを指定できません。CSS の font と同じように指定できると説明されていますが、line-height に相当する数値は無視されるので注意が必要です。

enchant.js のメッセージ表示部分で行の高さが反映されず詰まりました。



// テキスト表示部分の処理は省略しています
var message = 'Where is a pig! I am very hungry... Give me a pig!';
var label = new Label();
label.color = 'black';
label.text = message;

// フォントサイズを75px, 行の高さを75pxに指定するが無視される
label.font = '75px/75px fantasy';

game.currentScene.addChild(message);


Canvas APIの仕様では line-height に相当する値は 'normal' に固定されるようです。
配列を利用して1行ずつ手動で行間を開けることにしました。


var messages = [
    'Where is a pig!',
    'I am very hungry...',
    'Give me a pig!'
];
for(var i = 0; i < messages.length; i++) {
    var label = new Label();
    label.color = 'black';
    label.text = message;
    label.font = '75px fantasy';
    label.y = 75 * i;  // 手動で高さを調整
    game.currentScene.addChild(message);
}

参考
- W3C HTML Canvas 2D Context, Level 2 Nightly 
http://www.w3.org/html/wg/drafts/2dcontext/html5_canvas/#text-styles

2013年2月10日日曜日

マインスイーパー逆式を公開

ブラウザゲーム「マインスイーパー逆式」を公開しました。
PC・スマートフォン・タブレットどれでも遊べます。


普通のマインスイーパーは、数字を見て爆弾の位置を当てるゲームですが、逆式では爆弾を見て数字を当てます。
最初からすべての爆弾の位置が表示されており、空いているマスに入る数字を素早く入力するゲームです。
オンラインランキングに対応しており、他のプレイヤーのタイムと競い合うことができます。
HTML5対応のゲームライブラリ enchant.js を使って開発しました。
ソースコードは github にて公開中です。