仮想マウスイベント

仮想マウスイベント

jQueryMobileでは、タッチとマウスによるイベントを透過的に扱う仮想マウスイベントが使える

仮想マウスイベントは、
jQueryで使えるマウスイベントの
click
mousedown
mouseup
mousemove
mouseover
の先頭に
v
を付けたイベント名になる

以下は仮想マウスイベントのメモ

vclick
マウスクリック
もしくは
スクリーンタップ

vmousedown
マウスクリック
もしくは
スクリーンに触れたとき

vmouseup
マウスのボタンを離したとき
もしくは
スクリーンから指を離したとき

vmousemove
マウスが要素内に入ってきたとき
もしくは
スクリーンをタップしたまま指を動かしたとき
座標は現在タップしている位置になる

vmouseover
マウスが要素内に入ってきたとき
もしくは
スクリーンをタップしたまま指を動かしたとき
座標は最初にタップした位置になる

注意点としては、
vmousemove
vmouseover
の場合、スクリーンをタッチして上下に滑らすと
一緒に画面がスクロールし
期待した値が取得できない

このため、
preventDefaultを使い、
ブラウザのイベント伝播を防ぎ
ブラウザのスクロールを防ぐ必要がある

$("#box").on("vmousemove",function(e){

//ブラウザのデフォルト動作無効化
e.preventDefault;

//座標取得
x = e.pageX;
y = e.pageY;

});

となる

スクロール位置の検出

スクロールの開始と静止を検知するイベント

スクロールの開始を検知するscrollstartイベント
そして、スクロールの終了を検出するscrollstopイベント
の実装方法

例えば
一番上までスクロールしたら
1px下へスクロールさせ
ブラウザのnavigation bar を隠す

こうすると、画面が見やすくなる

$(window).on("scrollstop",function(e){

//スクロール位置が一番上のなったら
if(document.body.scrollTop== 0){

//縦方向へ1pxスクロールする
window.scrollTo(0,1);
}

});

このように、スクロール位置は
document.body.scrollTop
で取得できる

あと、Twitterみたいに、画面の一番下へ
スクロールしたら次のデータを読み込んで表示する
というように、一番下までスクロールしたことを検知するには

$(window).on("scrollstop",function(e){

//一番下までスクロールしたことを検知
if((document.body.scrollTop + window.innerHeight) == document.height){
//一番下までスクロールしたときの処理

}

});

となる

このように、
一番下までスクロールしたときの
スクロール位置である scrollTop

スクリーンの縦幅になる window.innerHeight
を足して
document.height
つまり、画面の縦幅と同じなら
一番下に達したと判断できる

端末の向き不向き検知するイベント

端末の向きを検知するorientationchangeイベント

jQueryMobileでは、端末の向きの変更を検知する
orientationchangeイベントが定義されていて
これを使うには

$(window).on('orientationchange',function(e){
orientation = e.orientation;
});

orientationの値は
縦から横向きになると landscape
縦なら portrait
になる

Androidアプリでも
縦はportrait
横向きなら landscape
になる

スマホのタッチイベントについて

スマホのタッチイベントについて

タッチイベントの種類のメモ

tap
マウスをクリック、もしくは
タッチスクリーンをタップしたたときに発生する
これはvclickと基本的に同じ

taphold
クリックしてボタンを押しっぱなし
もしくは
タップして長押しすると発生

swipe
素早く指を滑らすか
もしくは
クリックして素早くマウスを動かすと発生

swipeleft
素早く指を左に滑らすか
もしくは
クリックして素早くマウスを動かすと発生

swiperight
素早く指を右に滑らすか
もしくは
クリックして素早くマウスを動かすと発生

tapの
よくある使い方は
手書きアプリとか、お絵かきアプリ

書き方としてはまず領域を
divとか
canvas
て決める

とりあえず、今回はdiv

<div id="box" style="width:300px; height:300px;"></div>

次に、Javascriptで座標を取得する

$(document).on("tap","#box",function(e){

//座標取得
x = e.pageX;
y = e.pageY;

});

tapイベントのみ、イベントが発生した座標取得ができる

また、PCブラウザなど
マウスデバイスの操作でもタッチイベントの取得が可能

jQuerymobileの問題対処

問題対処のための自分なりのルールを作っておくとバグが減る

なお、ルールは書籍やサイトなどを参考に後々変更していく予定

対処ルールその1

画面遷移を利用するとき、別の画面に同じidがあってもイベントが設定されないようにする

このためには、以下のような書き方をする

$(document).on("pageinit","#text",function(e){
$(this).on("click","#btn",function(e){
alert("hello");
});
});

この書き方をする理由は
pageinitイベントの中でイベント定義することで
画面に対するイベントをまとめて定義できるから

これは、ある画面に対するイベント定義を書いた場所が分散すると、コードがわかりにくくなるから

また、thisによるデリゲードを使うことで
この画面にイベントを追加しているのがわかりやすくなる

ちなみに、デリゲードとは
要素の子要素の中のセレクタにマッチする要素にイベントを追加すること

対処ルールその2

ready()を使わない

jQueryMobileを使うときに
ready()は、基本的に最初に画面を読み込んだときしか実行されない

このため、ready()ではなく pageinitイベントを使うことで初期化処理を書く

対処ルール3

すべてのイベント定義は1つのJavascriptファイルへまとめる
理由は、jQueryMobileは
2画面目以降のhead要素内のscript要素を実行しないから

このため、最初の画面で、全画面分のイベント定義をしておく

これをevent.jsとか
custom.jsとかにして読み込んでおく

jQueryMobileの注意点

jQueryMobileのイベント定義の注意点

2ページ以降はhead要素のscriptが実行されない
これは、jQueryMobileは、2画面目以降のDOMは
AjaxでHTMLを取得し
画面をレンダリングしている
このとき、data-role=”page”で定義された要素以外は無視するため
2画面目以降のhead要素は読み込まれない

このため、1画面目に読み込ませるページで
Javascriptを読み込ませる

jQueryMobileでは、

<div data-role="page">

</div>

の間で管理しているので
普通のHTMLと同じように考えると
表示されないことがあるので注意

次の注意点として、セレクタで指定したイベントが、複数のページで動作することがあるということ
これは、data-role=”page”ごとで管理しているけど
id とかクラスが同じところがあると
識別がされず実行されてしまう
対策としては、被らないようにユニークなもので id=”” class=”” の中身を指定すること

そして、イベントの書き方がたくさんありすぎること
自由なのはいいけど、自由すぎてバグになりやすい

例えば、ボタンを押したらhelloと表示することさえ5つのやり方がある

その1

$(document).on("pageinit","#text",function(e){
$(this).on("click","#btn",function(e){
alert("hello");
});
});

その2

$(document).on("pageinit","#text",function(e){
$(e.target).on("click","#btn",function(e){
alert("hello");
});
});

その3

$(document).on("pageinit","#text",function(e){
$("#text #btn").on("click",function(e){
alert("hello");
});
});

その4

$(document).on("pageinit","#text",function(e){
$("#text").on("click","#btn",function(e){
alert("hello");
});
});

その5

$(document).on("click","#text #btn",function(e){
alert("hello");
});

このように、いくつかやり方はあるため
自分なりのルールを決めておくとわかりやすいしバグの防止にもなる

イベント追加と削除

jQueryMobileのイベント処理

$(#mybutton).on("click",function(e){
alert("スイッチオン!");
});

これだと
イベントを追加する要素の読み込み完了後でないと
イベント追加ができない

このため、追加したいイベントの前に
イベント追加scriptを書くと
正しく動作しない

このため、イベント追加したい要素の後へscriptを書くことになる

これが静的、つまりあらかじめ書いておくやり方

次に、動的、つまりプログラミングによる制御でイベント追加するやり方

これは、最初はHTMLに書かれてなくて
後から表示されるときに追加される

Twitter、Facebook、メール閲覧ソフトなどは
情報の更新で新しい情報表示しているのは
後から要素を追加している

あと、ほとんどの場合
JavascriptはHTMLのbodyの中じゃなくて
headの中へ書いている

こういった場合のイベント追加には

Javascriptの構文で

$(document).on(イベント名, セレクタ, ハンドラ)

となる
イベント名は、clickとかで
セレクタは対象のid
ハンドラは行う処理

例えば

<button id="save">保存</button>

このボタンへイベント追加するなら

$(document).on("click",""save",function(e){
   //保存する処理
});

とする

この追加したイベントを削除するには
off()を使う

通常は、Webアプリならイベントを削除はやらない

これは、画面遷移すると、すべてのイベントがクリアされるから

しかし、jQueryMobileだと
デフォルト動作で最初に読み込まれた画面がAjaxで次々と別画面を読み込んで画面を切り替え表示してしまう

つまり
通常のwebアプリとは違い
jQueryMobileの場合は
イベントを削除しない限りずっと残る

ボタンやテキストボックスなどのイベントは
コンポーネント固有なのであまり影響ないけど
スクロールイベントとか
各種センサー、位置情報などは
必要のない画面へ遷移しても処理し続け
思わぬ動作をすることがある

このため、一度追加したイベントは
off()で削除する

構文は

$(window).off("イベント名")

イベントの削除は
画面遷移して、今の画面を離れるときに使うことが多い

$(document).on("追加したいイベント","追加対象のid",function(e){
$(window).off("削除するイベント");
});

日付入力UI変更

日付入力UI変更

スロット画面みたいな日付入力以外にも
カレンダーから入力する方法もある

予約サイトとかだと
この方がわかりやすい

日付入力方法を変えるには
data-options=””
でmodeを指定する

data-role=”fieldcontain”
でjQueryMobileのフォーム作成

<div data-role="fieldcontain">
<label for="date">カレンダー</label>
<input type="date" name="date" id="date" data-role="datebox" data-options='
{"mode":"callbox",
"dateFormat","YYYY/MM/DD"}'/>
</div>

となる

グリッドレイアウト

グリッドレイアウトの利用

jQueryMobileでは、グリッドレイアウト支援機能がある

グリッドレイアウトは
均等な長さで部品を並べるときに使える
グリッドレイアウトを使うには

class=”ui-grid-a”
というように
カラム数を指定して
並べたい要素へ
class=”ui-block-a”というように指定する

ちなみに、
ui-gridで指定できるのは a~dになる
aが2
dが5
というようにカラム数を指定する

並べたい要素へ指定する
ui-block は、カラム数+1なので
ui-grid-d
なら
使えるui-blockは
ui-block-e
までになる

もし、
グリッドレイアウトで
ボタンを2つ並べたいのなら

<div class="ui-grid-a">

<div class="ui-block-a">
<button>保存</button>
</div>

<div class="ui-block-b">
<button>キャンセル</button>
</div>

</div>

となる

もし、ボタンを3つ並べて表示するなら

<div class="ui-grid-b">

<div class="ui-block-a">
<button>ホーム</button>
</div>

<div class="ui-grid-b">
<button>お気に入り</button>
</div>

<div class="ui-grid-c">
<button>検索</button>
</div>

</div>

となる

さらに、複数行にして
テレビのリモコンみたいにするなら
子要素の
class=”ui-block”を繰り返すことで簡単にできる

[/html]
このように、
class=”ui-block-a”
から
class=”ui-block-c”
の繰り返しを3回することで
3×3のマスになるように配置している

ただ、グリッドレイアウトに関しては導入するなら
jQueryMobileよりも
Bootstrapのほうが楽かもしれない