前回の WordPress ウィジェットで cookie を使う の続きということで、さっそくページをリロードさせるための条件を付け加えていこうと思います
処理概要
手順としては、こんな感じの処理となります
WordPress側 | 方向 | ブラウザ側 | |
1 | cookie からブラウザ幅データ取得 | ← | ページ読み込みのリクエストを送る |
2 | ページデータ出力 (JavaScript コード、リロード判定用データ、ブラウザ幅データに応じたコンテンツデータを送る) |
→ | 現在のブラウザ幅と cookie に保存されているブラウザ幅を取得 |
3 | cookie がないか、ブラウザ幅に変化があれば、cookie を保存 | ||
4 | 2番のページデータ出力を停止して、1番から再実行 | ← | リロード条件に一致すればリロード要求 |
5 | リロードしない場合は、ページデータを表示して終了 |
動作としては、3つのケースに分けられます
- 最初のリクエスト(1→2→3→4→1→2→5)
- ブラウザ幅が同じか、リロード条件に一致しない場合(1→2→5)
- ブラウザ幅が変わりリロードする場合(1→2→3→4→1→2→5)
JavaScript 実行タイミング
今回は、ブラウザ幅データを cookie に入れて渡すという手法を取っている関係上、JavaScript コードを必ず <head> タグ内に入れる必要があります。
実行するタイミングは、ページのロードが完了した時点でなく、スクリプトファイルが読み込まれた直後に実行させます
すなわち、<head> タグ読み込みが終了する前に、リロードする必要があるかどうかを判断して、リロードが必要なら <body> タグを読み込むことなく最初の読み込みを停止して、リロードすることで極力無駄な動作を行わないようにします
また、is_mobile_text ウィジェットの出力条件設定値がありますので、ブラウザ幅が変化しても、この出力条件の判定に違いがでなければリロードは不要となります
使用するのは、WordPress ウィジェットでAjaxを使う:潜入編 で紹介した下記関数です
wp_enqueu_script で、HTMLの <head> タグ内を指定して JavaScript ファイルを読み込む為のスクリプトを挿入させます
wp_localize_script を使用して JavaScriptへウィジェットの出力条件設定値をグローバル変数として渡します。従ってこのデータも <head> タグ内に挿入する必要があります
必要な設定値を抽出する
当初は、要求されたページに配置されているウィジェットのみを対象とした出力条件設定値が取得出来ればと思ったのですが、ウィジェット出力関数の widget() は、既に <head>タグ内のデータは構築された後にしか呼び出されません じぇじぇ (^_^;)
しかたないので、ウィジェットの __construct() 関数で必要な条件設定値を取得する必要があります
この時点では、要求されたページで使用されているウィジェットかどうかを簡単に判定することは出来ませんので、表示されるかどうかは分からないが、サイドバーに設定されているウィジェットの設定値を取得しました
get_option と wp_get_sidebars_widgets 関数を組み合わせて、有効なウィジェットの設定値を抽出することが出来ます。これをウィジェットの __construct() 内に記述します
//この時点では、どのウィジェットが対象かまだわからないので、全ての有効な is_mobile_textウィジェットを抽出 $wg_base = $this->id_base; $wg_opt = get_option($this->option_name); $wg_nums = array_filter( array_keys( $wg_opt ), 'is_int'); $active = array(); $setdt = array(); $sidebars_widgets = wp_get_sidebars_widgets(); if ( is_array($sidebars_widgets) ) { //使用していないウィジェットを除外する foreach ( $sidebars_widgets as $sidebar => $widgets ) { if ( 'wp_inactive_widgets' == $sidebar ) { foreach($wg_nums as $id){ $wgname = $wg_base.'-'.$id; if (! in_array($wgname, $widgets) ) $active[] = $id; } break; } } //ウィジェットのブラウザ幅判定値を取得 foreach($active as $id){ $minpx = $wg_opt[$id]['smallest']; $maxpx = $wg_opt[$id]['largest']; $setdt[$id] = array('min' => $minpx, 'max' => $maxpx); } } //JavaScript が<head> 内で読み込み直後に実行されることを想定している //最新のブラウザ幅データ取得のため JavaScriptからリロードさせる場合あり wp_enqueue_script( 'jquery' ); wp_enqueue_script( 'IMT-handle', plugin_dir_url( __FILE__ ) . 'is_mobile_getwidth.js', array( 'jquery' ), false, false ); //JavaScript へブラウザ幅変化時の判定用のデータをセット wp_localize_script('IMT-handle', $wg_base.'_option', json_encode($setdt) );
これで、狙いどうり <head> タグ内にスクリプトコードと判定値をセットさせることが出来ました
JavaScript 判定処理
スクリプトへ判定値を渡すことが出来てしまえば、後は簡単です
前回紹介した JavaScript の getBrowserSize()関数を修正します
function getBrowserSize() { var ns = {}; ns['width'] = jQuery(window).width(); ns['height'] = jQuery(window).height(); var gc = getJsonCookie("browser_viewport"); if(gc === null) { //クッキー作成 setJsonCookie("browser_viewport", ns, '/'); //クッキー再読み込み gc = getJsonCookie("browser_viewport"); if(gc !== null) { //クッキーが有効ならリロード window.stop(); window.location.reload(true); } } else if(ns['width'] !== gc['width'] ) { //クッキー更新 setJsonCookie("browser_viewport", ns, '/'); //変化した幅値が is_mobile_text ウィジェットの表示条件に影響するか var rlfg = false; var options = null; if(typeof 'is_mobile_text_option' !== 'undefined'){ options = JSON.parse( decodeURIComponent( is_mobile_text_option ) ); for(var id in options){ var min = options[id].min; var max = options[id].max; if((min <= ns['width'] && ns['width'] <= max) && (min <= gc['width'] && gc['width'] <= max)) continue; else if(!(min <= ns['width'] && ns['width'] <= max) && !(min <= gc['width'] && gc['width'] <= max)) continue; else { rlfg = true; break; } } } if(rlfg){ window.stop(); window.location.reload(true); } } }
判定値は、複数あることを想定して json 形式で渡しているので、ループで回しながら、ブラウザ幅の変化が出力条件の判定に影響しているか調べて、リロードが必要かどうかチェックします
以上で2回にわけて、cookie を使用したブラウザ幅の判定機能付きのテキストウィジェットの実装を行なってみました
JavaScript, cookie ともに有効になっている必要がありますが、wp_is_mobile 関数等での HTTPユーザーエージェントによるデバイスの判定を使わなくても、シンプルにブラウザの幅データからモバイルユーザーか判定出来るのではないかと思います
リロードさせると言うのが、ちょっとスマートではないですが、他にうまい方法がないですかね