おそらく、すべてのWeb開発者は、サイトに検索を実装する必要に直面しています。 かなり一般的なソリューションはApache Solrです。 Drupal開発の世界では、これも例外ではありません。 SolrをDrupalと統合し、ファセット検索を実装するために、
search_api 、
search_api_solrおよび
facetapiモジュールがあります 。 ただし、ほとんどの場合、ページ、つまりajaxをリロードせずに検索結果とファセットフィルターを更新する必要があります。 そして、
drupalの世界ではいつものように、
d.orgには、時間とユーザーによってテストされた(または幸運としてテストされていない)必要なことを行うモジュールがあります。 この場合、
ajax_facetsです。
Ajaxファセットは、ファセット検索フィルターで使用できるいくつかのタイプの「ウィジェット」を提供するモジュールです。 これらは「範囲スライダー」、「複数のチェックボックス」、「選択ボックス」、「リンク」です。 これらの「ウィジェット」の値を変更すると、フィルターと検索結果がajaxによって更新されます。 わあ ただし、モジュールが履歴APIのフレンドであれば、さらに良いでしょう。 つまり、フィルターの各状態を履歴に保存します。これにより、ユーザーはページをリロードすることなく、ブラウザーの戻るボタンと進むボタンを使用して検索履歴をたどることができます。
挑戦する
もちろん、この機能の必要性と実装への関心はそれ自体では生じませんでした。 プロジェクトの1つは、ajax_facetsをhistory APIと友達にすることでした。 私が話したいこと。
解決策
通常、問題の解決策は、既製の解決策、または少なくともパッチを見つけることから始まります。 既成のソリューションはありませんでしたが
、パッチが見つかりました 。 プロジェクトの問題トラッカーの
説明から判断
すると 、彼は必要なことだけを行いました。 しかし、残念なことに、パッチは古く、古いモジュールブランチ(7.x-2.x)にのみ適していました。 そのアイデアは非常に簡単です。検索結果とフィルター自体を更新するためにajax_facetsがサーバーから正常な応答を受け取った瞬間に、ブラウザーの履歴にフィルターの現在の状態を保存します。 また、「戻る」ボタンと「進む」ボタンをクリックして、履歴からフィルターの保存状態を取得し、保存状態のパラメーターでフィルターと検索結果を更新する要求を送信します。
アイデア自体の効率をテストするために、見つかったパッチを現在のモジュールブランチ(7.x-3.x)に
移植しました。 すべてがうまくいきました。 ただし、改善が必要でした。 つまり、この機能が、履歴APIをサポートしていない古いブラウザーで動作することを望みます。 タスクは簡単です。 history APIをエミュレートする
history.jsがあります。 一方、
ライブラリモジュールを依存関係に追加することになるため、このライブラリにハード依存関係を追加したくありませんでした。 誰もそのようなパッチを受け入れなかったでしょう。 ajax_facetsモジュールを更新しており、依存関係に不要なライブラリがあると想像してください。 はい。また、history.jsの形式の古いブラウザーのサポートも必要ありません(たとえば、古いブラウザーをサポートしないだけです)。 そのような状況を避けるために、私はすべてをもう少し柔軟にすることにしました:
- サーバー側では、モジュールライブラリとhistory.jsライブラリの可用性を確認します。 依存関係が見つかった場合、フロントエンド側にフラグ「history.jsが使用可能です。履歴APIを使用できます」を渡します。
- クライアント側では、ブラウザが履歴APIをサポートしているかどうかを確認します(ネイティブまたはhistory.jsを使用)。 その場合、期待どおりにすべてを実行します。 それ以外の場合、標準のajax_facetsの動作を取得します(パッチの前と同じ)。
実装
最初の項目は次のように達成されます。
依存関係が見つからない場合は、「ステータスレポート」ページにヒントを示します。
function ajax_facets_requirements($phase) { $requirements = array(); $t = get_t(); switch ($phase) { case 'runtime': $description = $t('For now browser ajax history feature works only in HTML5 browsers. If you want to get this feature on HTML4 browsers you need to install libraries module and download history.js library.'); $value = $t('Libraries module not installed.'); if (module_exists('libraries')) { if (!libraries_get_path('history.js')) { $description = $t('For now browser ajax history feature works only in HTML5 browsers. If you want to get this feature on HTML4 browsers you need to download history.js library.'); $value = $t('Library history.js not found.'); } else { $description = $t('For now browser ajax history feature works both in HTML4 and HTML5 browsers.'); $value = $t('Works with history.js library'); } } $requirements['ajax_facets_message'] = array( 'title' => $t('Ajax Facets'), 'description' => $description, 'value' => $value, 'severity' => REQUIREMENT_INFO, ); break; } return $requirements; }
history.jsライブラリが見つかった場合は、フラグをフロントエンド側に転送します。
function ajax_facets_add_ajax_js($facet) { static $included = FALSE; if (!$included) { ...
2番目の段落の実装は、例としてpushStateラッパー関数とともに示されています。
Drupal.ajax_facets.pushState = function (state, title, stateUrl) {
ところで、history.jsには、考慮する必要のある興味深い機能が1つあります:
statechangeイベント
は 、ブラウザーの履歴ボタンが押されたとき、および例えばHistory.pushState()メソッドを呼び出して履歴がプログラムによって更新されたときに発生します ネイティブ履歴APIの実装では、ブラウザーには
onpopstateイベントがあり、ブラウザー履歴ボタンがクリックされたときにのみ呼び出されます。 不必要にトリガーされるstatechangeを回避するには、ブラウザーの履歴を更新する前にこのイベントからサブスクライブを解除してから、再度サブスクライブする必要があります。
おわりに
ターンキーソリューションを見つけて適用できるとは限りません。 しかし、それは非常にクールです。 これにより、以前使用されていたモジュールが内部でどのように機能するかを確認することができます。 そして、最終的に、あなたが提案するソリューションが人気のあるプロジェクトにコミットするのは素晴らしいことです。 これは、次回誰か他の人がそのような問題を抱えることがないことを意味します。
ここで完全な差分を見ることができ
ます 。