2011/07/28

[Android] Android バージョン2.*ではクリックイベントの判定が遅い

Android2.*ではtouchendからclickまでの時間がちょっと長いようだ。
それで少しはまった。

TwiiterみたいにAjaxで読み込みながらどんどん縦に長くなるページで、ページの下の方まで進んだ時、スマートフォンではページのTOPに戻るのがけっこう面倒だった。(すごいスクロールすれば戻れる)

まあ、これは使用者に優しくなかろうと思って、Ajaxで読み込む度に「このページのTOPに戻る」ボタンを設置していた。
このボタンそれぞれにイベント設置しとけばいいんだろうけど、何ページも読み込むとボタンがいっぱい出てくるし、Ajaxで読み込むたびにボタンにイベント設置するのもなんか無駄が多そうだなと思ったんで、jQueryのデリゲートみたいに、枠全体にtouchendイベントを設置して、戻るボタンがタッチされた場合はページTOPにアニメーションで移動するようにした。

iPhoneではOK。Android3.*でもOK。
でもAndroid2.*では戻るボタンをクリックして、ページトップまでアニメーションしている途中に別のページに移動してしまう時がある。

調べてみると、touchendでスクロールが開始した後にclickイベントが起きて、どういう判定かわからんが、たまたまクリックしたと判定された場所がリンクの上だったりすると、そのリンク先に移動してたみたい。

他のバージョンでは起きないことだったから少し時間かかってしまった

【追記】
これってontouchendじゃなくてonclickで動くようにするだけで解決できたっぽいぞ…

2011/07/25

[MySQL] 外部キーに設定されているカラムを主キーに設定する

テーブルの主キーを変更する必要があった時に、ちょっとはまってしまったのでメモ

はじめ、1つの外部キーを主キーにしていた。
テーブルにあるもう一つの外部キーも主キーにして、複数の主キーを持つテーブルにしたい

いったん主キーを削除して再設定しようとして
ALTER TABLE table DROP PRIMARY KEY;
これがエラー。
外部キーだからか?

それでは、新しく主キーになるカラムを設定しようとして
ALTER TABLE table ADD PRIMARY KEY (id);
とするとエラー
Multiple primary key defined

結局、どっちのカラムも一旦外部キーを解除してから主キーに設定することで解決した。
主キー設定後、また外部キー設定をした

外部キー解除
ALTER TABLE テーブル名 DROP FOREIGN KEY 外部キー名;
外部キー名は
SHOW CREATE TABLE テーブル名
で見られる

主キーの登録
ALTER TABLE テーブル名 ADD PRIMARY KEY (カラム名[, カラム名2]);

外部キーの再登録
ALTER TABLE テーブル名 ADD FOREIGN KEY (カラム名) REFERENCES 参照先のテーブル名(参照先の主キー名);

[cakePHP] selectタグでデフォルトで選択する項目を指定する

[cakePHP 1.3の話 ]

フォームのselect要素を作成したい場合は

//コントローラー
$this->set('list', $this->Model->find('list'));

//ビュー
$form->select('Model.fieldname', $list);

でできるけど、このselectの項目の1つを選択状態にする方法がわからなかった。

見つけた方法は
$form->input('Model.fieldname', array(
  'type' => 'select',
  'options' => $list,
  'selected' => 選択したいアイテムの番号を指定
));

「選択したいアイテムの番号を指定」ってのは…
find('list')で取得したデータは

array(
[1] => 'hello',
[3] => 'good bye'
);
という風にキーがそのテーブルのIDになってくるので、このIDのことです。

2011/07/21

[JavaScript] onloadよりも DOMContentLoadedを使おう

window.onload = function{....
って書き方をよくするけど、コレだとHTMLだけでなく、画像の読み込みまで完了しないとイベントが起きない。

document.addEventListener("DOMContentLoaded", function(){...

で書くとHTMLの解釈が終わった時点で、画像の読み込みを待たずにイベントが起きる。
使えないブラウザもあるみたいなので注意

参考
これでできる! クロスブラウザJavaScript入門



[JavaScript] スマートフォンでのtouchendで指が要素の外でも反応してしまう

スマートフォンのclickイベントは、シングルクリックかダブルクリックかの判定をするために、0.数秒処理を待つので、体感的にもっさりとした感じを受ける。

なので、clickではなくtouchendイベントでいろんな処理をしていくんだけど、touchend時にターゲットの要素の外でもイベントが起きちゃって困った。

具体的には
ボタンの上に指をON。touchstartイベント
指を動かして、指をボタンの外に出す。touchmoveイベント
ボタンの外で指をはなす。touchendイベント
これで、ボタンに設定していたtouchendイベントが動き出す。

使う側としたら、スクロールやスワイプ?フリック?なんかをしたつもり なのに、なんか動き出したって感じかな。

この違和感をなくすために、指を動かしたら、touhcendイベントは起きないようにした。

var startY,
      endY;
 
function touchStart(e){
  //最初に触った位置を記憶
  startY = endY = e.touches[0].pageY;
}
               
function touchMove(e){
  //動いている間指の位置を記録
  //最後に触った位置で変数の値が決まる
  endY = e.touches[0].pageY;
}

function touchEnd(e){
  //iPhoneでは10ピクセルほどあそびがあって、それ以上動かさないと移動したと判定されない
 //Android2.1だと15ピクセルくらい
  if(Math.abs(startY - endY) === 0){
    //処理
  }
}

target.addEventListener('touchstart', touchStart);
target.addEventListener('touchmove', touchMove);
target.addEventListener('touchend', touchEnd);




touchendでendYを取得しないのは、Androidのバージョンによっては、touchendでevent.touchesが取得できなくなるから
動かした距離によって処理が変わったりしないならtouchmoveイベントが起きた時点でisMoved=trueみたいにフラグをたてると良さそう

2011/07/19

[JavaScript] Androidで touchend時に touchイベントが取得できない

Androidのバージョン2.2、2.3で起きた問題。

function touchend(event){
  event.touches[0] //undefinedになる
  event.touche.length //0
}

バージョン2.1までは取得出来ていたのに。
2.1以前で作っていたサイトは2.2でtouchendイベントが取得出来なくてうまく動かなくなってるかも

俺のやってたのは指の位置を取得する処理だったので、


var endX = 0;

function touchstart(event){

  //触った時点で値を格納
  endX = event.touches[0].pageX;
}

function touchmove(event){
  endX = event.touches[0].pageX;
}

function touchend(event){
  //endXを使った処理
}

↑みたいな感じでtouchmove中にずっと位置を取得し続けて、最後に格納された値で位置を判断することにした。

バージョンによって、ちょこちょこ動かなくなる箇所がある。
そしてこれからバージョン3以降もテスト開始...

2011/07/17

[cakePHP] htmlヘルパーまとめ

■リンクを作成する
$html->link(リンク文字列, url, 属性);

■画像を表示
$html->image(画像パス, 属性);

随時追加していきます