開発者ブログ
リファレンス(仕様詳細) » シーン検討中機能

シーン検討中機能

Last modified by tom on 2016/01/21, 13:16

#428 シーン遷移機能・メインシーンコンテナでの遷移時の、シーン間パラメータのURL保存方式の検討

こちらについてはほぼ実装完了なので特に記載しません。

以下は実装済み。

  • h5.u.obj.serialize、h5.u.obj.deserializeを使用
  • クエリパラメータを使用する場合、サーバーサイドで使用するものとの併存について考慮(パラメータ名のプレフィクス等)
  • クエリパラメータではなくハッシュを使う方式も提供
  • パラメータのサイズ制限

以下は実装中。→実装完了

  • シーン遷移時にURLにパラメーターを保持しない方式の提供(履歴遷移時は「再表示不可」等の画面を表示)

#441 Router機能の実装

Routerのドラフト

↑を踏まえ、実装は以下の様になった。(外部公開はしていない)

Routerクラス

シングルトン実装。二回目以降の生成は初回のインスタンスを返す。
二回目以降の引数はルーティングルールoption.routesのみ有効。これを既存のものとマージする。(配列の末尾追加。優先度は後のほうが低くなる)

URLのチェック対象となるのは、HirtoryAPI使用の場合はドメインルートより後、Hash使用の場合はHash(#より後)を対象とし、先頭からベースURLを除いたもの。
ただし、Hash使用の場合でもHash値がない場合はドメインルートより後を使用する。これをここでは「ルーターURL」と呼称する。
evaluateメソッド経由で実行された場合は、その第一引数から「ルーターURL」を取得する。

引数は以下。

  • 第一引数 option … 以下のプロパティを持つオブジェクト。
    • urlHistoryMode … URL履歴保持方法指定。初回生成時のみ有効。以下の値が設定可能。※シーン機能リファレンスの「遷移時のURL変更方式の切り替え[ver1.2.1]」と同じ。
      • 'hash' … シーン遷移パラメーターをハッシュに格納する。
      • 'none' … URLを変更しない。
      •  'fullreload' … Ajaxを使用せず、ページ全体を再読み込みする(通常の遷移)。
      •  'history' … HTML5 History APIを使用してURLを変更する。History APIが使用できない場合はハッシュを使用する。
      •  'historyOrHash' … 'history'と同義。
      •  'historyOrError' … HTML5 History APIを使用してURLを変更する。History APIが使用できない場合はエラーとする。
      •  'historyOrNone' … HTML5 History APIを使用してURLを変更する。History APIが使用できない場合はURLを変更せずに遷移する。
      •  'historyOrFullreload' … HTML5 History APIを使用してURLを変更する。History APIが使用できない場合はAjaxを使用せずに遷移する(通常遷移)。
    • baseUrl … ベースURL。指定しない場合は「ルーターURL」のドメインルートがベースになる。指定した場合は、ルーティングルールチェック前に「ルーターURL」から先頭のベースURLが除去される。
    • urlMaxLength … 遷移先URL最大長。デフォルト1800。これは「ルーターURL」ではなく、URL自体が対象。
    • routes … ルーティングルール。以下の形式の配列。
      [{test:/*(文字列|正規表現|関数)*/}, func:/*対応処理関数*/}, ...]
      • testには、URLをチェックするためのルールを以下の様に指定する。
        文字列の場合 … ルーターURLすべてを指定。(完全一致。パラメーター以下もすべて指定)
        正規表現の場合 … ルーターURLとマッチする正規表現を指定
        関数の場合 … ルーターURLを仮引数とし、対象の場合true、対象外の場合falseを返却する関数を指定
      • funcには、ルールマッチ時に実行する関数を指定する。第一引数にルーターURL、第二引数にevaluate経由の場合に指定されたデータが設定される。この際、処理としては別のルールのものを実行する場合は、別のURLを返却値として指定する。この場合、ブラウザURLは変更されないが、内部的にはURLのルーティングを行っているため、ルールがループしないよう注意すること。返却値がない場合は何もしない。

startメソッド

生成時に指定された条件、および実行環境に基づいた、URLの監視を開始する。
History API使用であればpopstate、Hash使用であればhashchangeをイベント購読する。
すでに開始されている場合は何もしない。

引数は以下。

  • 第一引数 option … 以下のプロパティを持つオブジェクト。
    • silent … 監視開始時にその時点のURLに対応した処理を実行しない場合にtrueを指定する。デフォルトfalse。

navigateメソッド

生成時に指定された条件、および実行環境に基づいて、URLを変更する。
History API使用であればURL自体、Hash使用であればHashを変更する。
監視が開始されていなければ何もしない。

引数は以下。

  • 第一引数 to … 遷移先指定
    • silent … 監視開始時にその時点のURLに対応した処理を実行しない場合にtrueを指定する。デフォルトfalse。
  • 第二引数 option … 以下のプロパティを持つオブジェクト。
    • replace … 前の画面の履歴を残さずに遷移する場合にtrueを指定する。
    • mode … 動作モード指定。以下が設定可能。指定しない場合は、生成時に指定された条件、および実行環境に基づいて動作する。
      • 'none' … URLを変更せずに対応処理を実行する
      • 'fullreload' … Ajaxを使用せず、ページ全体を再読み込みする(通常の遷移)
      • 'silent' … URLのみ変更し、対応処理は行わない。

遷移先が同一URLである場合の動作について

遷移先URLが現在と同一の場合、「URLを変更せずに遷移する」以外のケースで、
「現URLに対応した処理を実行、ブラウザ履歴は追加しない」
という動作にする。

  • HistoryAPI pushStateは、同一URLでもブラウザ履歴が追加される。その後のブラウザバックでpopstateも発生する。
  • hash使用の場合は同一URLではブラウザ履歴は追加されず、hashchangeも発生しない。
  • href使用の場合は同一URLではブラウザ履歴は追加されないが、通常画面更新は発生する。が、URLにハッシュがついていると、画面更新は発生しない。(スクロールのみ)

これらの差異を吸収するよう実装する。

パラメーターの順序差異を考慮した同一性のチェックは、ここでは行わない。

stopメソッド

生成時に指定された条件、および実行環境に基づいて、URLの監視を停止する。
History API使用であればpopstate、Hash使用であればhashchangeのイベント購読を停止する。
開始されていない場合は何もしない。

evaluateメソッド

URL変更なしでの対応処理実行。ブラウザURLは変更しないが、指定されたURLに対応した処理を実行する。

引数は以下。

  • 第一引数 url … 指定URL
  • 第二引数 contextualData … 対応処理実行時パラメータ。これが指定された場合、ルーティングルールのfuncの関数実行時、その第二引数として設定される。(funcの返却値により再度ルーティング・実行される際には設定されない)

compareUrlメソッド

URLの比較。
仮引数が相対指定であっても絶対指定に変換してから比較する。

引数・返却値は以下。

  • 第一引数 sbj … 比較するURL
  • 第二引数 obj … 比較するURL。指定しない場合は、現時点のURLを対象とする。
  • 返却値 … 同一の場合はtrue、異なる場合はfalse

#440 シーン遷移時のアニメーション効果

  • changeScene(navigateに変更予定)の引数でtransitionで指定。
  • 現状'default'のみ。アニメーションなしで遷移。
  • registerSceneTransition関数でtransition登録可能。現在内部関数で非公開。公開すれば各開発者が独自に遷移効果を登録できる。
  • 遷移効果はreplaceBoxに倣い、以下をあらかじめ登録する予定。
    • slideLeft
    • slideRight
    • slideUp
    • slideDown
    • pushLeft
    • pushRight
    • pushUp
    • pushDown
    • openLeft
    • openRight
    • openUp
    • openDown
    • fade
    • none ※defaultと同じだが、あえて追加すべきか
  • 現状だと、registerSceneTransitionに設定できるのは以下のメソッドを定義したクラス。
    • onChangeStart … 遷移前。デフォルトはインジケーターを表示。
    • onChange … 遷移。デフォルトでは前のDOMを消して、次のDOMをapppend。
    • onChangeEnd … 遷移後。デフォルトではインジケーター消去
  • が、これだとアニメーション時はうまくいかないので以下とする予定。
    • onChangeInit … 遷移処理開始直後。主にインジケーターを表示。
    • onChangeStart … 遷移前。主に次のDOMを所定位置に配置。
    • onChange … 遷移。主に前のDOMと次のDOMをアニメーションさせて入れ替え。
    • onChangeEnd … 遷移後。主に前のDOMを削除、インジケーター消去。※インジケーター削除は別メソッドにしたほうがよいかも。
  • Transition親クラスを作ったほうがよさそう。registerSceneTransitionに設定するのは、クラスではなくクラス定義とし、こちらでextendして使用する、等。
  • シーンを戻る遷移の場合は、遷移時のアニメーションの逆再生を行う。ブラウザバック等の場合でも同様。
    • このため、メインシーンコンテナの場合、URLに遷移ごとにインクリメントするインデックスを持たせたい。戻る遷移の場合、直前のインデックスから-1になるので、これで戻ったことを検知する。
    • これをURLに持たせずに、スクリプト内で情報を保持する方式もある(jQueryMobileが該当)が、リロードされると全情報が消えるので、その後はアニメーション逆再生ができなくなる。
    • 直接アクセス時は「進む」遷移時の効果で表示。遷移効果はURLのFWパラメーターに保持している。
    • メインシーンコンテナでない、通常のシーンコンテナの場合は、次項の「シーン機能・前画面の保存とブラウザの戻る等での再表示」で保持されている場合のみ戻ることができる。その場合は遷移効果を逆再生する。
  • アニメーション中は、同一画面内に前シーンと次シーンが同時に存在することになる。以前問題になったのは、ラジオボタンで同じname属性が前後のシーンで使われていたため、チェック状態がおかしくなった点。(前シーンを保持して再表示したときに、チェックが全部はずれてた) 入力要素を使用する場合はformタグで囲ってもらう等の制約が必要。更に、formタグで意図しないsubmitをしないように注意する必要がある。(type指定なしのbuttonタグ、単一テキストボックス内Enterでのsubmit抑制等)
  • アニメーション時はシーン要素をposition:absoluteで処理するため、シーンコンテナのサイズが自動でシーン要素に依存していると、正しくアニメーションできない。シーンコンテナをブロック要素に限定したとしても、縦幅については何らかの指定が必要になる(しないと縦が潰れる)。考えられるのは、
    • シーン遷移処理前に現状のコンテナ要素の縦幅(px)を保持
    • シーン要素をposition:absolute→縦幅が潰れたら、保持した縦幅を指定。(潰れたら、というのはちょっと表示上よろしくないかもしれない。。)
  • できれば、縦幅は指定する、としたいが、次善としては、指定していない場合は、その時点の縦幅で固定するという制約が発生する、としたい。

#438 シーン機能・前画面の保存とブラウザの戻る等での再表示

  • シーンコンテナのchangeScene(navigateに変更予定)メソッドの引数で、save:trueが指定されると、遷移元のシーンのコントローラー、DOMをシーンコンテナが保持する。
    • DOMは保持用DOMをスクリプトで作ってappendしておく。こうしないとDOMイベント購読が保持できない。
     this.scene.navigate({
        to : 'to.html',
        save : true
      });
  • 戻る場合は、backメソッドを呼ぶ。
     this.scene.back();
  • これらはメインシーンコンテナ・シーンコンテナで共通だが、細かい点で動作は異なる。

メインシーンコンテナ

  • saveしてのnavigate時、上述の「URLに格納するインデックス」をキーにして、シーンコンテナでコントローラーを保持する。
  • 遷移時は、保持したコントローラーに現在のURLのインデックスに該当するものがあるか探査し、あればこれを表示する。
  • 遷移時(戻る場合も)、現在より上のインデックスで保持されているものはすべて削除する。
  • 現段階では、保持したシーンをすべてクリアするタイミングは、シーンコンテナの削除・初期化時のみ。それ以外については、後述の「シナリオ」で検討する。
  • その画面にnavigateType:'once','exchange'で遷移した場合は、そこからの遷移時のsave指定は無効。
  • リロードされるとすべてクリアされるので、確実に同じ画面を表示したい場合は、サーバーサイドで保持する等の対応が必要。

通常のシーンコンテナ

  • saveしてのnavigate時、コントローラーをシーンコンテナが持つスタックにpushする。
  • saveが続いた場合はpushを続ける。saveせずに遷移した場合、その時点でスタックをすべてクリアする。
  • back時、スタックがあればpopして使用する。なければ何もしない。(遷移なし)

  • DOMを再表示する場合、その中のスクロール可能要素のスクロール状態がすべて初期化されてしまう。
    これを保持・復元する機構が必要。(DATA属性に持って復元、属性クリア)
  • それ以外でも、再表示時に行うべき処理を登録できる仕組みが必要か。
  • ただし、大前提として、履歴として保持したコントローラー、DOMを、遷移先から操作することは禁止する。(遷移先以外の別処理からも同様)
    • これをやってしまうと、「履歴」の意味が崩壊して、開発が異常に複雑になる恐れがある。。 ブラウザの戻る等と連動している点を考慮してください。
    • 同じ画面を別状態で再表示する場合は、「進む」遷移で表示する。
  • 再表示時に行う処理も、あくまで「正しく前の状態に戻すため」の処理のみにする。外部からのパラメーターも受けつけない。

#437 シーンコンテナ内の複数シーン対応

  • 以下のようなシーンコンテナで、最初、もしくはデフォルト指定されたシーンを表示し、それ以外を隠す。
<div data-h5-container>
 <div data-h5-scene>
   <h2>最初に表示される</h2>
 </div>
 <div data-h5-scene>
   <h2>最初は表示されない</h2>
 </div>
</div>
  • 現状でも、初期表示対象のシーン以外はscanの対象外としているが、非表示の処理は行っていない。
    • DOMツリーから外して保持するほうがアニメーション等がやりやすい。
  • 別のシーンに遷移する場合は、以下の様にする。
     this.scene.navigate({
        scene : 'sub'
      });
  • 同一ページであればtoは不要となる。
  • 別ページの特定コンテナ・特定シーンに遷移する場合は、以下の様にする。
     this.scene.navigate({
        to : 'to.html',
        container : 'test_container',
        scene : 'sub'
      });
  • toでのcontainerが単一、もしくはcontainerがメインシーンコンテナであれば省略可。
  • toを指定せずにcontainerを指定することはできない。(同一ページ内別コンテナのシーンに遷移する、は認めない)

#439 シーン機能・シナリオの実装

  • 複数場面のグループと、その遷移を定義するもの。複数画面で一機能を実現する場合等で使用。
  • シナリオがほしい理由:
    • DOMcacheとかがあるときに、シナリオでくるんだページの集合の単位で、シナリオ完了時にインスタンスを破棄する、みたいなことがしたい
      • インスタンスの破棄、共有変数の破棄など
      • #438と同時に考えるべき
    • ページ遷移のインデックスのリセット
  • できれば線形遷移のみとしたい。分岐やループがあると非常に複雑になる。。
  • 主に想定される機能は以下。
    • シナリオ内で共有する変数を持つ。(※ただし、履歴遷移時に矛盾が発生しないよう考慮する必要がある)
    • シナリオ開始、終了時の処理が定義できる。
      • 途中からの開始、または途中での終了も同様。
    • シナリオを中断、別シナリオへ遷移し、戻ってから再開できる。
      • 中断の場合は終了処理は行わない。

  • これらの処理を、メインシーンコンテナで行う場合、どのようにシナリオ状態をURLに保持するかを考える必要がある。
  • 遷移方法としては、これまでのtoによる遷移先の物理的指定ではなく、シナリオファイルを指定する形になる。
  • 一案としては以下。
//sampleSenario.js
registerSenario('sampleSenario', [
  {id : 'hoge', to : 'from.html'},
  {id : 'fuga', to : 'to.html'}
];
//遷移
this.scene.navigate({
  senario : 'sampleSenario',
  senarioId : 'hoge'
});

メインシーンコンテナの場合、URLは以下の様になる。(イメージです)

xxx.html?scenario=sampleSenario&senarioId=hoge

Copyright (C) 2012-2016 NS Solutions Corporation, All Rights Reserved.