まめしみ

やったことを淡々と書く

jQueryMobile(1.0rc2)でkeepNativeが復活


 

以前書いた「jQueryMobile(1.0b2)のスタイルを無効化する」でkeepNativeが使えなくなった話をしましたが「1.0rc2」で復活してるようです。

 

「1.0b2」から何度かバージョンが上がって「1.0rc2」がリリースされました。Change logをさら〜っと見てたらこんなの見つけました!

Allow users to define keepnative on page elements – Change allows for more flexibility

 

commit log探ってポイントを抜粋してみました。

 

定義してるとこ

$.widget( "mobile.page", $.mobile.widget, {
	options: {
		theme: "c",
		domCache: false,
		keepNativeDefault: ":jqmData(role='none'), :jqmData(role='nojs')"
	},

	_create: function() {

		this._trigger( "beforecreate" );

		this.element
			.attr( "tabindex", "0" )
			.addClass( "ui-page ui-body-" + this.options.theme );
	},

	keepNativeSelector: function() {
		var options = this.options,
			keepNativeDefined = options.keepNative && $.trim(options.keepNative);

		if( keepNativeDefined && options.keepNative !== options.keepNativeDefault ){
			return [options.keepNative, options.keepNativeDefault].join(", ");
		}

		return options.keepNativeDefault;
	}
});

 

実際に使ってるとこ

(function( $, undefined ) {

$.widget( "mobile.widget", {
	// decorate the parent _createWidget to trigger `widgetinit` for users
	// who wish to do post post `widgetcreate` alterations/additions
	//
	// TODO create a pull request for jquery ui to trigger this event
	// in the original _createWidget
	_createWidget: function() {
		$.Widget.prototype._createWidget.apply( this, arguments );
		this._trigger( 'init' );
	},

	_getCreateOptions: function() {

		var elem = this.element,
			options = {};

		$.each( this.options, function( option ) {

			var value = elem.jqmData( option.replace( /[A-Z]/g, function( c ) {
							return "-" + c.toLowerCase();
						})
					);

			if ( value !== undefined ) {
				options[ option ] = value;
			}
		});

		return options;
	},

	enhanceWithin: function( target ) {
		// TODO remove dependency on the page widget for the keepNative.
		// Currently the keepNative value is defined on the page prototype so
		// the method is as well
		var page = $(target).data( "page" ),
			keepNative = page && page.keepNativeSelector();

		$( this.options.initSelector, target ).not( keepNative || "" )[ this.widgetName ]();
	}
});

 

enhanceWithinで各widgetの初期化が実行されます。その時点でkeepNativeで指定したセレクタは除外してます。
enhanceWithinが呼ばれないwidget(listviewなど)には意味が無いです。
data-role=”listview”指定してる時点で無効にする事はないので問題ないでしょう。

 

試したところ1.0b2以前のようにclass指定での一括除外もできました。
※この記述はjQueryMobileの読み込みより先に

$(document).bind("mobileinit", function(){
  $.mobile.page.prototype.options.keepNative = ".data-role-none, .data-role-none *";
});

TODOに今のとこ同じだからprototypeで定義するよ!的なこと書いてあるのでまた変更されるかもしれませんが、、、

jQueryMobile(1.0b2)でフォーカスが残る問題の対応


 

jQueryMobile(1.0b2)でフォーカスの装飾が残る問題がありました。
inputがページ上部にあると発生することがあります。

 

ソース解析したので原因まとめてみます。

フォーカスの装飾はcssのclass「ui-focus」で定義されています。
そしてfocusイベントでaddClass、blurイベントでremoveClassされます。
読み込み時にfocusさせclassが追加されますが実際にはfocusがちゃんとあたっていません。
そのため別の場所にfocusが移動してもblurイベントが起きずclassが残るようです。
jQueryMobileのバグともブラウザの仕様の問題とも解釈できる内容ですね。

 
1.0rc1では解消されていました。(もっと以前に解消されてるかも)
可能であればjQueryMobileのバージョンをあげてしまうのが手っ取り早いと思います。

既に公開中だとバージョンあげるのも怖いので対応方法を。
まずは該当部分の抜粋。

1.0b2

#2144行目
//define first selector to receive focus when a page is shown
focusable = "[tabindex],a,button:visible,select:visible,input",

#2192行目
//direct focus to the page title, or otherwise first focusable element
function reFocus( page ) {
    var lastClicked = page.jqmData( "lastClicked" );

    if( lastClicked && lastClicked.length ) {
        lastClicked.focus();
    }
    else {
        var pageTitle = page.find( ".ui-title:eq(0)" );

        if( pageTitle.length ) {
            pageTitle.focus();
        }
        else{
            page.find( focusable ).eq( 0 ).focus();
        }
    }
}

 

1.0rc1

#2223行目
//define first selector to receive focus when a page is shown
focusable = "[tabindex],a,button:visible,select:visible,input",

#2282行目
//direct focus to the page title, or otherwise first focusable element
function reFocus( page ) {
	var pageTitle = page.find( ".ui-title:eq(0)" );

	if( pageTitle.length ) {
		pageTitle.focus();
	}
	else{
		page.focus();
	}
}


セレクタ「focusable」で最初に見つけたものにフォーカスを当ててます。
これがよろしくないので、1.0rc1と同様に「page.focus();」にすればいいと思います。
ソースを弄るのを避けたい場合、「page.find( focusable ).eq( 0 )」がinputにならないように調整して対応することもできます。

 
1.0rc1でfocusableの定義残ってますがここ以外では使用されていません。消し忘れ?

複数のphpをインストールしている環境でphpize


 

cakephp2.0を試そうと思ったらDB接続にPDOを使っていた。
拡張モジュールpdo_pgsqlを追加したときのメモ。
この環境では複数バージョンのphpをインストールしています。

 

ポイント

  • 追加したいバージョンのphpのphpizeを実行
  • configureのオプション「–with-php-config」で追加するバージョンのphp-configを指定
#インストール時に使用したphpディレクトリ内のpdo_pgsqlに移動
#残ってなければ再度ダウンロード
cd ~/parts/php-5.3.8/ext/pdo_pgsql

#phpize実行
/usr/local/php-5.3.8/bin/phpize

#「--with-php-config」を指定してconfigure
#「--with-pdo-pgsql」は適宜変更すること
./configure
--with-php-config=/usr/local/php-5.3.8/bin/php-config /
--with-pdo-pgsql=/usr/local/lib/postgresql83

make
sudo make install

 

php.iniを編集してrestart。

sudo vi /usr/local/php-5.3.8/lib/php.ini
===================================
extension_dir = "/usr/local/php-5.3.8/lib/php/extensions/no-debug-non-zts-20090626/"
extension=pdo_pgsql.so
===================================

sudo apachectl restart

#確認(pdo_pgsqlがあればOK)
/usr/local/php-5.3.8/bin/php -m

jQueryで画像サイズを調整して携帯サイトをスマートフォン対応させる


 

240px基準で作成してある携帯サイトをスマートフォン対応させる方法

携帯サイトをスマートフォンでみたら画面いっぱいに表示した画像が小さくてレイアウトが崩れた経験ありませんか?

PCサイトがあるならそちらに割り振るほうがいいのですが、
スマートフォンの画面サイズに合わせて拡大縮小すればそこそこ見栄えよくなります。
ついでに左右に余白いれて見やすくしてみます。
 

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.6, user-scalable=yes>
<script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script>
$(function(){$("html").hide();});
$(window).bind('resize load orientationchange', function(){
  $("img").css("zoom" , ($(window).width() - 10)/240 );
  $("body").css("padding", "0px 5px");
  $("html").show();
});
</script>
<head>

今回は240px基準で作成してある前提です。
まずはmetaタグのviewportを追加します。

(画面サイズ - 余白) / 240

こんな感じに比率を求めてzoom処理します。
あとは余白をつけてお終いです。

これだけでいい感じになります。
「orientationchange」にもbindしてるので画面を横向きにしてもOK!!

 

※追記
画像がズームされるときの動きが気になったので、ズーム処理は非表示状態で行うように調整。

node.jsで変数の値をファイルに保持する(永続化)


 

当然のことながらアプリを再起動すると変数が初期化されます。
Bear : まめしみGAMEでは累計アクセス数をリセットしたくないので変数の値をファイルに保持して永続化してみました。

app.jsから抜粋

//import
var express = require('express');
var app = module.exports = express.createServer()
var io = require('socket.io').listen(app);-
var fs = require('fs');

var totalFile = __dirname + '/tmp/total.txt';
var total = function(){
    var ret = 0;
    //ここは起動時の処理なので同期処理を使用する
    //一度a+モードで開く。
    //ファイルがなければファイルが作成される。
    var fd = fs.openSync(totalFile, 'a+');
    fs.closeSync(fd);
    //totalファイル読み込む。
    data = fs.readFileSync(totalFile, 'utf-8');
    if(data){
        ret = parseInt(data);
    }
    return ret;
}();

//イベント
io.sockets.on('connection', function(socket){
    total++;
    //totalファイルに記録しておく
    fs.writeFile(totalFile, ''+total, function(err){
        if(err){
            throw err;
        }
    });
}

起動したときに変数totalの値をファイルから読み込んでいます。

コメントにも書いてありますが起動時の処理なので同期処理にしています。
ここで非同期にするメリットは何もありません。
totalの値を確定させることが大事。

connectionイベントでtotalをインクリメントしてファイルに書き込むようにします。

 

DBを使うよりお手軽に永続化できます。

nodejs + express + socket.io でゲーム作った


 

nodejs + express + socket.io でゲーム作った

Bear : まめしみGAME
 

ゲーム内容はあれですが、、、
以下のことが気になっていたのでそこそこデータのやり取りしているゲームつくりました。

  • どれくらいリアルタイムなのか?
  • websocketとxhr-pollingでどれくらい違うのか?
  • 3G回線ではどうか?
  • 各ブラウザの挙動は?
  • サーバーの負荷は?

 

通信方式、サーバーのload average、メモリ使用量とかも表示しています。

敵、アイテム位置情報はサーバー側で管理しているので当たり判定はサーバーでしています。
なかなかリアルタイムで出来てると思いますがどうでしょう?
さすがにスマフォで3G回線カクつきます。。。

 

みなさんも複数ブラウザ立ち上げてどんなもんか見てみてください。

 
Bear : まめしみGAME

socket.ioがnpmインストールできないときの対応


 

centOSでsocket.ioをnpmインストールするとエラーになった。

npm install socket.io

=====
npm ERR! tar "-mvxpf" "-" "-o" "-C"
=====

 

centOSのtarはバージョンが古い。
yumでインストールできるのは1.1系。
1.2系が必要なのでソースからtarを入れた。

cd ~/parts
wget http://ftp.gnu.org/gnu/tar/tar-1.26.tar.gz
tar zxf tar-1.26.tar.gz
cd tar-1.26

#古いものをuninstall
sudo rpm -e --nodeps tar

./configure
make
sudo make install

インストールできたがtarコマンドのパスがおかしくなって使えなくなった。
ついでにOSアップデートもしてたのでrebootしたらパス通りました。。。

 

sokect.ioインストール

npm install socket.io

うまくいきました!

githubで証明書エラー(certification error)になったときの対応


 

以下のサイトを参考にさせていただきました。
gitやcurlやwgetでGitHubにアクセスするとcertification errorになる原因を調べてみた

 

DigiCertのEV SSL用ルート証明書(DigiCert High Assurance Ev Root CA)が標準パッケージに含まれていない。ってのが問題なようなので証明書追加しました。

 

とりあえず.crtファイルを探す。

sudo find / -name *.crt

 

「/etc/pki/tls/certs/ca-bundle.crt」が見つかった。
OpenSSLパッケージに含まれているものらしい。

 
追加する。

cd ~/parts/
wget https://www.digicert.com/testroot/DigiCertHighAssuranceEVRootCA.crt
sudo chmod 666 /etc/pki/tls/certs/ca-bundle.crt
sudo cat DigiCertHighAssuranceEVRootCA.crt >> /etc/pki/tls/certs/ca-bundle.crt
sudo chmod 644 /etc/pki/tls/certs/ca-bundle.crt

 
エラーでなくなりました!!

さくらVPS弄り ~その7~ gitインストール


 
gitをインストールします。
 
Git – Fast Version Control System

 

gitインストール

1.gitインストール

cd ~/parts
wget http://www.kernel.org/pub/software/scm/git/git-1.7.6.tar.gz
tar zxvf git-1.7.6.tar.gz
cd git-1.7.6
./configure --with-curl=/usr/local
make
sudo make install

 

2.補完設定

mkdir ~/etc
cp ~/parts/git-1.7.6/contrib/completion/git-completion.bash ~/etc/

vi ~/.bashrc
===========================================
#git completon
source $HOME/etc/git-completion.bash
===========================================
. ~/.bashrc

 
これでtabによる補完が効くようになります。

 
以下をやるとプロンプトにブランチ名を表示できます。
お好みで弄るといい感じです。

vi ~/.bashrc
===========================================
PS1='[\u@\h:\W]$(__git_ps1 "\[\e[32m\](%s)\[\e[0m\]")$ '
===========================================
. ~/.bashrc

 

3.gitの設定

git config --global user.name 'your name'
git config --global user.email  'abcdefg@sample.com'
git config --global core.editor vim
git config --global merge.tool vimdiff
git config --global color.status auto
git config --global color.branch auto
git config --global color.interactive auto
git config --global color.diff auto

Pro Git – Pro Git 1.5 使い始める 最初のGitの構成を参考にお好みの設定にしてください。

さくらVPS弄り ~その6~ node.js & npmインストール


 
node.jsとnpm(node package manager)をインストールします。
 
isaacs/node – GitHub
isaacs/npm – GitHub

 

node.js & npmインストール

1.node.jsインストール

wget http://nodejs.org/dist/node-v0.4.11.tar.gz
tar zxvf node-v0.4.11.tar.gz
cd node-v0.4.11
./configure
make
sudo make install

 

2.npmインストール

curl http://npmjs.org/install.sh |sudo sh

 
こんなエラーが出た。。。

npm cannot be installed without nodejs.
Install node first, and then try again.

Maybe node is installed, but not in the PATH?
Note that running as sudo can change envs.

PATH=/usr/bin:/bin

 
sudoしたときにPATHが引き継がれていない模様。
sudoの設定にenv_keepというところがあるので、そこに「PATH」を追加します。

sudo visudo
===============================================
Defaults    env_keep = "PATH COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR \
                        LS_COLORS MAIL PS1 PS2 QTDIR USERNAME \
                        LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION \
                        LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC \
                        LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS \
                        _XKB_CHARSET XAUTHORITY"
===============================================

 
リトライ!

curl http://npmjs.org/install.sh |sudo sh

 
うまくいきました。

/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm.js
/usr/local/bin/npm_g -> /usr/local/lib/node_modules/npm/bin/npm.js
/usr/local/bin/npm-g -> /usr/local/lib/node_modules/npm/bin/npm.js
npm@1.0.27 /usr/local/lib/node_modules/npm
It worked