DOMキャッシュについて

DOMキャッシュについて

jQueryMobileは、DOMキャッシュ機能を持っている

これほ、一度表示した画面、つまりDOMをjQueryMobileの中にキャッシュして、キャッシュしたDOMを表示する機能

これは、メニュー画面など、
頻繁に表示されるページに利用する

DOMキャッシュで
すべての画面をキャッシュするには
jQueryMobileを初期化時に
$.mobile.page.prototype.options.domCache
をtrueにする

$(document).on("mobileinit",function(){
$.mobile.page.prototype.options.domCache = true;

});

これは、mobileinitイベントで定義する

次に、特定の画面のみキャッシュする方法

すべての画面をキャッシュするのはリソースの無駄なので行わない

キャッシュするのは
メニュー画面など
頻繁に再訪が発生するページのみにする

キャッシュ画面の指定は
画面の要素、つまり
data-role=”page”
に対して
data-dom-cache=”true”
を設定する

ソースにすると

<div data-role="page" data-dom-cache="true" id="menu">

</div>

なお、DOMキャッシュは、アプリケーションキャッシュを使うなら不要になる

次の画面を先読みするプリフェッチ機能

次の画面を先読みするプリフェッチ

ある画面から次の画面に移るときに
画面が変わるタイミングでデータ読み込みがあると
画面が表示されるまで時間がかかることがある
特に低速回線の場合は多発する

この対処としては、jQueryMobileで提供されているプリフェッチ機能を使えば
ユーザーに今の画面を表示している間に
次の画面のデータを事前に読み込んでおける

このプリフェッチ機能により
あらかじめ次の画面を読み込んでおくことで
スムーズに画面遷移ができる

これは、アンケートとかユーザー登録みたいな次に遷移するページが決まっているときに使う

プリフェッチ機能を使うには
リンクする a要素へ
data-prefetch=”true”
を設定する

<a href="next.html">次へ</a>

ただし、プリフェッチ機能を乱用すると
ユーザーが見ない画面も取得してしまうため
サーバーに負荷がかかるし
ネットワーク負荷もかかる
このため
プリフェッチ機能は、次にみる可能性の高い画面のみ設定すること

ちなみに、photoSwipeは
デフォルトで画像を表示している間にプリフェッチ機能で前後の画像を取得している

このため、画像をプリフェッチしながら表示するなら
PhotoSwipeを使うと便利

いろいろと使えそうなプリフェッチ機能だけと
アプリケーションキャッシュを使えば
プリフェッチ機能は使わなくても代用できる

$.getScript()で遅延ロード

$.getScript()でスクリプトの遅延ロード

大きなサイズのJavascriptライブラリーを使う場合
scriptタグで全部読み込むより
一旦画面を表示してから
スクリプトを読み込んだほうがWebアプリのレスポンスがよくなる

また、特定条件のときのみ必要なライブラリーは
ライブラリーを動的に読み込むようにして
不要なJavascriptのロードを避ける

Javascriptを動的に読み込むのに使うのが
$.getScript()
を使う

例えば、iOSでは日付が使えるけど
Androidではできない
なので、Androidなら
jQueryMobile DateBoxを読み込む
というように、ifで判定して使う

<script>
if(navigator.userAgent.indexOf("Android")!=-1){

$.getScript("http://dev.jtsage.com/cdn/datebox/latest/jquery.mobile.datebox.min.js",function(data,status){
$.getScript("http://dev.jtsage.com/cdn/datebox/i18n/jquery.mobile.datebox.i18n.ja.utf8.js",function(data,status){
//Javascript読みこみ処理

});

});

}
</script>

jQueryMobileでは、デフォルトで最初にアクセスしたとき
トップページでJavascriptを読み込むのが望ましい

そして、このときにトップページに必要のないJavascriptは
$.getScript()
を使うことで
まずはトップページを表示して
その後に必要なJavascriptを読み込むようにすれば
低速回線でもストレスなく表示することができる

フォームの遅延ロード

フォームの遅延ロード

Ajaxのフォームも遅延ロードで作成可能

ただし、これもただ追加しただけでは
jQueryMobileが適用されないため

フォームコンポーネントを追加した時点で
trigger(“create”)
を呼び出す必要がある

$.ajax({
type:"POST",
url:"./form.html",
dataType:'html',
success: function(data){

//データ追加
$("#corapsible-form").append(data);

//jQueryMobile反映
$("#corapsible-form").trigger("create");

},
error:function(msg){
alert(msg.responseText);
}

});

これで、あとはhtmlで
追加する領域の指定

<div data-role="corapsible" data-corapsed="true" id="acordion" name="acordion">
<h3>動的フォームの挿入</h3>
<form id="corapsible-form"></form>
</div>

続いて、挿入するhtmlファイル

このやり方のメリットは、後から追加できるため
メンテナンスが楽なこと
そして作業の分担ができること

全体的なUIの設定と
フォーム内容担当を分けることができる

アンケートなどではかなりの量になるので
都度アンケート内容だけ変更することもできる

<div data-role="fieldcontain">
<label for="slider">スライダー</label>
<input type="range" name="slider" id="slider" value="0" min="0" max="100" />
</div>

<fieldset data-role="controlgroup">
<legend>好きなタイプは?</legend>
<input type="checkbox" name="rpg" id="rpg" class="custom"/>
<label for="rpg">RPG</label>

<input type="checkbox" name="action" id="action" class="custom"/>
<label for="action">アクション</label>

<input type="checkbox" name="puzzle" id="puzzle" class="custom"/>
<label for="puzzle">パズル</label>

</fieldset>

<div data-role="fieldcontain">
<fieldset data-role="controlgroup">
<legend>使うosは?</legend>

<input type="radio" name="os" id="android" value="android"/>
<label for="android">Android</label>

<input type="radio" name="os" id="ios" value="ios" checked="checked"/>
<label for="ios">iOS</label>

<input type="radio" name="os" id="other" value="other"/>
<label for="other">両方</label>
</fieldset>
</div>

遅延ロードで必要なデータのみ取得

遅延ロードで必要なデータのみ取得

大量のデータや読みこみに時間がかかるデータを画面に表示するときに
かなり時間がかかる

この場合、最低限の画面を表示し
徐々にデータを表示したり
ユーザーがWikipediaのコンテンツみたいに
アコーディオンを開いたらオンデマンドで
データを取得、表示するという遅延ロードが有効

すごい時間をかけて全部でるより
徐々に表示されるほうがストレスは少ない

jQueryMobileで、
リスト表示で
この遅延ロードをするにはコツがある

なぜなら
Javascriptで後からタグを追加しただけだとjQueryMobileのスタイルが適用されないから

なので、追加したら
listview(“refresh”)
をする必要がある

まず、実践するには

<script src="js/loadform.js"></script>

で自作スクリプトの読みこみ

次に、開閉したい場所の領域を

<div data-role="corapsible" data-corapsed="true" id="corapsible-list">
<h3>遅延ロードの実践</h3>
<ul data-role="listview" id="list">
</ul>
</div>

として設定

data-role=”corapsible”
は、開閉する指定

data-corapsed=”true”
で開いた状態にする
デフォルトは false で閉じた状態

http://dev.screw-axis.com/doc/jquery_mobile/components/content/collapsible/
を参考にするとわかりやすい

そして、処理はJavascript

途中で
$.mobile.showPageLoadingMsg()

$.mobile.hidePageLoadingMsg()
があるけど、これは
ローディングアイコンの表示、非表示をする

この動作サンプルとしては
http://www.atmarkit.co.jp/fdotnet/chushin/jqmobile_06/jqmobile_06_02.html
にTwitterのつぶやきを表示したりするサンプルがあるので
こちらを参考にするとわかりやすい

あと
data: “param1=123&param2=homuhomu”
これは
http://semooh.jp/jquery/api/ajax/jQuery.ajax/options/

http://phpjavascriptroom.com/?t=ajax&p=jquery_ajax_requests

jQuery $.ajaxでJSON・JSONP読み込みに使用する主なオプション


をみたかんじだと
サーバーip/json.php?param1=123&param2=homuhomu
になる

$.trim()

http://semooh.jp/jquery/api/utilities/jQuery.trim/str/
にあるように、空白の削除するメソッド
つまり
if($.trim($(“#list”).html()) ==””){
なら
id=”list”のタグの中身が空ならとなる

$.each()は
http://semooh.jp/jquery/api/utilities/jQuery.each/object%2C+callback/
にあるように、繰り返し処理をする
繰り返すのは
$(‘#list’).append(“

  • “+data[e]+”
  • “);
    でリスト追加処理

    $(document).on("expand","#corapsible-list",function(e,data){
    if($.trim($("#list").html()) ==""){
    $.mobile.showPageLoadingMsg();
    
    $.ajax({
    type:"POST",
    url:"./json.php",
    data:"param1=123&param2=homuhomu",
    dataType:'json',
    success:function(data){
    $.each(data,function(e){
    $('#list').append("<li>"+data[e]+"</li>");
    });
    $('#list').listview("refresh");
    $.mobile.hidePageLoadingMsg();
    },
    error: function(msg){
    alert(msg.responseText);
    $.mobile.hidePageLoadingMsg();
    }
    
    });
    
    }
    
    });
    

    そして、PHPファイルでデータの用意
    ファイル名は json.php

    <?php
    header('Content-type: application/json;charset=utf-8');
    $data = array("みかん","りんご","ブドウ","もも");
    echo json_encode($data);
    ?>
    

    json_encode()
    で配列をjson形式にしている

    Webアプリの通信量削除

    Webアプリのパフォーマンスチューニング

    まず、通信量の削減

    基本的に、ライブラリーを使うときには
    .min.js
    とついている圧縮版を使う

    自作のコードもできる限りツールや
    Webサーバーのモジュールで圧縮する

    圧縮にはgruntのプラグインなども使えそう

    あと、使われる物としては
    Google Closure CompilerでJavascriptのコード削減

    YUI Compressor によるJavascriptとスタイルシートのコード削減

    Apache のmod_deflate によるデータ圧縮など

    ただし
    Google Closure Compiler
    YUI Compressor
    についてはJavaが必要になる

    Google Closure Compilerは
    https://code.google.com/p/closure-compiler/
    を参考に

    また、Google Closure Compilerは、コマンドからの操作も可能

    http://www37.atwiki.jp/aias-closurecompiler/pages/16.html?&flag_mobilex=1
    の解説がわかりやすい

    このツールは
    改行などを削除し、コードを圧縮する

    使い方は

    java -jar compiler.jar --js ファイル名

    結果をファイルへ出力するには

    java -jar compiler.js --js ファイル名 --js_output_file 出力ファイル名
    

    とする

    また、ファイルを結合するなら

    java -jar compiler.js --js_output_file 出力ファイル名 元のファイル名 元のファイル名

    とする

    次に、YUI Compressor
    これは、Yahoo!が開発している
    Javascriptとスタイルシートの圧縮ツール

    詳しい使い方については
    http://stacktrace.jp/tools/yuicompressor/
    を参考に

    これも、コマンドから実行で行う

    CSSファイルを圧縮するには

    java -jar yuicompressor.jar --type css --charset utf-8 -o 出力ファイル名 圧縮したいファイル名

    となる

    これも2つのソースをまとめることが可能で

    jar -jar yuicompressor --type css --charset utf-8 -o 出力ファイル名 元ファイルその1 元ファイルその2

    とする

    次に、データ圧縮をする Apache mod_deflateについて

    HTTP 1.1をサポートするWebサーバーを使うと
    サーバー側で自動的に圧縮したデータをブラウザー側で解凍して表示できる

    Apacheの場合
    mod_deflateモジュールを使うことでできる

    まずは、http.conf
    つまり、Apache設定ファイルの中にモジュール読み込み設定があるか確認

    LoadModule deflate_modules/mod_deflate.so
    

    そして、
    http://httpd.apache.org/docs/2.2/ja/mod/mod_deflate.html#deflatecompressionlevel
    のリファレンスを参考に追記する

    DeflateCompressionLevel
    の値は、1~9で
    値を大きくすれば圧縮率はあがるけど
    代償としてサーバーの負荷も上がっていく

    devicePixelRatioと画面サイズ

    devicePixelRatioと画面のサイズ

    ピクセルが2倍になった状態で
    そのまま文字や画像を表示すると見かけ上のサイズが半分になり
    小さく表示される

    このため、鮮明な解像度の画面を使うときには
    文字や画像を拡大表示することで
    ちょうど良い大きさに拡大している

    このときに、何倍かするかという値が
    window.devicePixelRatio

    この値は、iPhone4以降なら 2.0
    ほとんどのAndroidなら 1.5

    あと、元々の画像の解像の値を
    物理値、物理座標といい

    修正された値は、
    論理値、論理座標という

    これは少し面倒だけど
    マウスイベントとか、タッチイベントの座標や
    cssでの設定は論理座標になるため
    Javascriptで制御するときには、論理座標になる

    スクリーンに対する情報は
    screen.height
    screen.availHeight
    window.innerHeight
    window.outerHeight
    などの値から情報を得られる

    注意点としては、OSにより値が
    物理値か、論理値か変わると言うこと

    iOSはすべて論理値なのに、Androidは物理値のものもある

    screen.height
    画面の高さ
    これは、ステータスバーなども含む
    Androidでは物理値扱い

    screen.availHeight
    利用できるスクリーンの高さ
    Androidでは物理値

    screen.innerHeight
    描画領域の内サイズ
    どっちも論理値になる

    screen.outerHeight
    描画領域の外サイズ
    Androidでは物理値

    Webアプリをネイティブアプリみたいに見せるには

    Webアプリをネイティブアプリみたいにみせる

    Webアプリをネイティブアプリみたいに見せるには
    アプリアイコンの登録と
    ブラウザバーやメニューを非表示にする

    まずは、アプリアイコンの登録

    これは、HTMLファイルのheadへ
    アプリアイコンへの設定をすることでできる

    <link rel="apple-touch-icon-precomposed" href="../images/icon_file.png"/>
    

    というように、
    href=””には、アイコンファイルへのパスを記述する

    アイコンのサイズは
    144×144がオススメ

    これは、アイコンのサイズが小さいと、
    解像度の高い端末だとボケて表示されてしまうから

    次に、アドレスバーの削除

    Androidでは、

    <meta name="apple-mobileweb-app-capable"
    

    が使えないため、Javascriptで制御する

    Androidでは、画面が1pxでも下へ移動するとURLバーが隠れるため
    この特性を使う

    $(document).on("mobileinit",function(){
    if(navigator.userAgent.match(/Android|iPhone/i)){
    $(document).on("pagechange",function()e,data){
    //1pxずらしてアドレスバーを隠す
    var hide_addressbar = function(){
    if(document.body.scrollTop==0){
    window.scrollTo(0,1);
    }
    }
    
    /*ページ縦幅がスクリーンの縦幅より狭い場合
    ページ縦幅をスクリーン+1して
    スクロールできるようにする*/
    if(navigator.userAgent.match(/Android/i)){
    var pageHeight = $(document).height();
    var windowHeight = window.outerHeight / window.devicePixelRatio;
    
    if(windowHeight => pageHeight){
    pageHeight = windowHeight+1;
    $('BODY').css('height',(pageHeight)+'px');
    }
    }
    hide_addressbar();
    
    //スクロール時に強制的に 1pxずらす
    $(window).on('scrollStop',function(){
    hide_addressbar();
    });
    });
    }
    
    });
    

    これは、Androidは、ページがスクリーンより短いと
    縦にスクロールできないため
    ページの縦幅を
    スクリーンの縦幅+1px広げることで
    スクリーン可能にしている

    それが

    if(navigator.userAgent.match(/Android/i)){
    var pageHeight = $(document).height();
    var windowHeight = window.outerHeight / window.devicePixelRatio;
    
    if(windowHeight => pageHeight){
    pageHeight = windowHeight+1;
    $('BODY').css('height',(pageHeight)+'px');
    }
    }
    hide_addressbar();
    

    の部分

    ただし、これだけだとせっかく隠しても
    ユーザーが上にスクロールすると
    隠したアドレスバーが出てしまう

    このため、その対処として
    スクロール時に画面が一番上に達したか
    チェックし、
    到達したなら強制的に1px下げることでアドレスバーを隠す

    その処理が

    $(window).on('scrollStop',function(){
    hide_addressbar();
    });
    

    2つのグラフ間の塗りつぶし

    2つのグラフ間の塗りつぶし

    塗りつぶしをするには
    fillBetweenを使う

    opts={
    
    fillBetween:{
    series1: 1,
    series2: 2,
    color:rgba(227,167,121,0.2),
    baseSeries:0,
    fill:true
    }
    }
    

    これは、トレンドを出すときに使える
    株価とか為替のレンジ範囲分析とか

    次に、基準値の表示

    グラフ上に、閾値や基準値を表示するには
    canvasOverlayプラグインを使う

    canvasOverlayプラグインを使うには
    HTMLでライブラリーを読み込む

    <script src="js/jqplot/plugins/jqplot.canvasOverlay.min.js"></script>
    

    次に、Javascriptのオプション項目で
    canvasOverlayを設定

    設定するには
    objects:{

    }
    の中で各種項目を設定していく

    opts={
    
    canvasOverlay:{
    show:true,
    objects:{
    {verticalLine:{
    x:2,
    lineWidth:2,
    lineCap:'butt',
    shadow:false
    }},
    {dashedHorizontalLine:{
    y:5,
    lineWidth:2,
    dashPattern:[8,16],
    lineCap:'round',
    shadow:false
    }}
    }
    },
    }
    

    となる

    objectsの中では、最初に線種を設定する
    利用できるものとして

    verticalLine
    垂直線

    dashedVerticalLine
    垂直線(点線)

    horizontalLine
    水平線

    dashedHorizontalLine
    水平線(点線)

    lineWidth
    線の幅

    lineCap
    線の端の設定
    buttは端形、roundなら丸くする

    dashPattern
    波線の長さと間隔の指定
    dashPattern:[8,16],
    というように、配列みたいに指定

    shadow
    陰を付けるかどうかをtrue/falseで指定