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(画像パス, 属性);

随時追加していきます

2011/07/15

[cakePHP] コントローラーでのルール

コントローラーはAppController を継承する
※間に1つ別のクラスを挟んだりしてもいいんだよな、多分…

-名前の定義
public $name
コントローラ名を定義する。1文字目は大文字。パブリックにする

-モデルの定義
public $uses = array('Table');
使うモデルの定義
そのコントローラーで使うモデルを定義しておく。
省略した場合は、コントローラー名の単数形のモデルを使う。
1つのテーブルしか使わないってことはそんなにはないよね?

-アクションの定義
function index(){}
メソッドとして登録
アクセスするURLは「/コントローラ名/アクション名」になる
省略した場合はindexアクション
php4の時は、メソッド名の最初を_(アンダースコア)で始めると、URLで指定してもアクセスできなかったみたい。
俺のとこはPHP5なんでprivateにしとけばいいんだろうけど。アンダースコアはいるのかな?試してみよう

-変数をビューに渡す
$this->set(変数名, 値)


cakePHP1.3からはfindAllはなくなったみたい。
find('all');で同じ動きになる

参考
CakePHPで作るToDoアプリ(1)

[cakePHP] cakePHPのデータベース、テーブルのルール

・データベース(以下DB)のテーブル名は複数形にする

・テーブルの主キーのカラム名はid

・作成日時はcreated、更新日時はmodifiedにする
※この名前にしておくと、自動で更新してくれる。

・外部キーに使用するカラム名は「関連付けたいモデル名」_id
※データベースの設定でprefixを付けていても、外部キーはprefixを無視してモデル名_idでつける


どれを単数形にして、どれを複数形にするかはすぐわすれてしまうなー

2011/07/13

[JavaScript] 要素を追加する

■子供要素を追加する方法

appendChildだと親要素の最後に子要素を追加できる

elem.appendChild(childElem);


先頭に追加したい場合はinsertBeforeを使う
insertBeforeは指定した要素の前に、新しい要素を追加できる

parent.insertBefore(追加したい要素, 既存要素);



なので先頭に追加したい場合は

parent.insertBefore(追加したい要素, parent.firstChild);


これで現状の最初の子要素の前に新要素を追加できる



■指定の場所に追加する

指定の要素の前に追加できる

node.insertBefore(elem);



参考
 [JavaScript] DOM Nodeに子ノードを



2011/07/12

JavaScriptで位置情報を取得する

スマートフォンサイトで位置情報を取得する処理があった。
コードはこんな感じ
if (navigator.geolocation) {
  navigator.geolocation.getCurrentPosition(function(pos){
    //取得成功時の処理
  }, function(){
    //エラー時の処理
  });
} else {
  error('not supported');
}

iPhoneではうまく動いたのに、Androidでは動かないけど、エラーも出ない。
確認してみるとnavigator.geolocationは確かにある。

調べてみると、Androidの設定によっては位置情報を取得できないみたい。
「設定」→「位置情報とセキュリティの設定」の中の「無線ネットワークを使用」と「GPS機能を使用」の両方にチェックを入れたら反応するようになった。
デフォルトで反応しないとなると、位置情報を使ったサービスを使わせるための引きこみが必要になるなー

※試したのはXPERIA SO-01B(Android 2.3)ってやつ。他人のもの(2人にお願いした)だったので、詳細はわからないけど、2人ともGPS絡みの設定はやったことないとのことなので、工場出荷状態だとGPSは反応しないみたい

2011/07/06

[JavaScript] 親要素・子要素・兄弟要素の取得方法

JavaScriptでの要素の取得方法。ライブラリばっかり使ってると忘れてしまうので

■親要素

element.parentNode


■子要素

子供一覧
element.childNodes //NodeListオブジェクトが返ってくる
※子要素がない場合でも、空っぽのNodeListオブジェクトが返ってくる

最初の子
element.firstChild

最後の子
element.lastChild


■兄弟要素


兄ちゃん要素
element.previousSibling

弟くん要素
element.nextSibling

改行なんかもTextノードだと認識されるので、注意




jQueryでの取得方法もまとめてます
jQuery親要素、子要素、兄弟要素取得のまとめ


参考
ノード木を探索する



2011/07/05

[iPhone] CSSアニメーションがちらつく場合

iPhoneでCSSアニメーションを使う場合、画面がちらついてしまう時がある。

俺の場合は、位置を移動させるtranslateXを-webkit-transitionでアニメーションさせようとした時に起きた。

Androidでは起きない症状。
translateXの指定をtranslate3dに変更することでちらつきはなくなった。

-webkit-transform: translateX(100px);

↓↓↓ 変更 ↓↓↓


-webkit-transform: translate3d(100px, 0px, 0px);


参考
スマートフォン制作のツボ最新を聞いてきた-CSS Nite,LP13

[iPhone] アニメーションは CSSでやるべし

iPhoneのアニメーションをJavaScriptでアニメーションすると非常にもっさりとして、コマ落ち気味の乙な動きになってしまうので、CSS3の-webkit-transitionを使用しようしようしよう。

イージングの種類が少ないのが残念だけど、動きの滑らかさはJavaScripとは比べ物にならない

参考
CSS3 変形処理を行う transform プロパティ