まめしみ

やったことを淡々と書く

Category : jQuery

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)でフォーカスの装飾が残る問題がありました。
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の定義残ってますがここ以外では使用されていません。消し忘れ?


 

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!!

 

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


 

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

Bear : まめしみGAME
 

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

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

 

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

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

 

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

 
Bear : まめしみGAME


 

jQueryMobileスタイルを適用したくなかったのでドキュメントを参考にやってみた。

 

//////////////////////////////////////////////////////////////////////////////////////////////////
追記
1.0rc2でkeepNative復活しました!
jQueryMobile(1.0rc2)でkeepNativeが復活
//////////////////////////////////////////////////////////////////////////////////////////////////

 

ドキュメントより抜粋。

 

Preventing auto-initialization of form elements

If you’d prefer that a particular form control be left untouched by jQuery Mobile, simply give that element the attribute data-role=”none”. For example:

 

If you’d prefer that a particular form control be left untouched by jQuery Mobile, simply give that element the attribute data-role=”none”. For example:

<label for="foo">
<select name="foo" id="foo"  data-role="none">
	<option value="a" >A</option>
	<option value="b" >B</option>
	<option value="c" >C</option>
</select>

Or, if you’d like to prevent auto-initialization without adding attributes to your markup, you can customize the selector that is used for preventing auto-initialization by setting the page plugin’s keepNative option (which defaults to [data-role="none"]. Be sure to configure this option inside an event handler bound to the mobileinit event, so that it applies to the first page as well as subsequent pages that are loaded.

$(document).bind('mobileinit',function(){
	$.mobile.page.prototype.options.keepNative = "select, input.foo, textarea.bar";
});

 

それぞれにdata-role=”none”を指定するか、keepNativeで除外するセレクタを設定できると書いてある。

が、、、、
data-role=”none”の指定は効いたがkeepNativeでのセレクタ設定ではダメだった。
ソースをみてみるとkeepNativeの扱いが1.0b2から大きく変更されてた。

 

1.0b1 (一部抜粋)

this.keepNative = ":jqmData(role='none'), :jqmData(role='nojs')" + (o.keepNative ? ", " + o.keepNative : "");

var allControls = this.element.find("input, textarea, select, button"),
    nonNativeControls = allControls.not(this.keepNative);

 

keepNativeに設定したセレクタを除外するようになっている。

 

1.0b2 (一部抜粋)

this.keepNative = ":jqmData(role='none'), :jqmData(role='nojs')";

$( $.mobile.slider.prototype.options.initSelector, e.target )
		.not( ":jqmData(role='none'), :jqmData(role='nojs')" )
		.slider();

 

keepNativeは除外セレクタとして使われていない。
その代わりにinitSelectorで初期化するセレクタを設定できそう。
今までのkeepNativeでは一括設定でしたが、それぞれのタイプごとに設定できるようになってるっぽい!
※上の例では「slider」

 

//////////////////////////////////////////////////////////////////////////////////////////////////
追記
1.0rc2でkeepNative復活しました!
jQueryMobile(1.0rc2)でkeepNativeが復活
//////////////////////////////////////////////////////////////////////////////////////////////////

 

今回はdata-role=”none”で対応したので試していませんが、initSelectorについてChange log に書いてありました。

Change logより抜粋

Exposed automatic initialization selectors on most widgets – The new option, initSelector is accessed through each of the widget plugins (select, slider, etc.) that expose options through the widget factory. This is used to define the selectors (element types, data roles, etc.) that should be used as the trigger to automatic initialization of each widget plugin. This allows developers to apply auto-initialization in more flexible ways.

コミットログはこちら