スマホ向けサイト 宿泊予約特典のレストラン空き再検索

スマホ向けサイト専用
All-in-One対応

機能概要

※スマホ向けサイト専用です

スマホ向けサイトでの宿泊予約特典のレストラン空き検索画面で、「時間の選択」の同一画面内で時間帯別での再検索が行えるようになります
また、「人数・時間の選択」画面で「時間帯」をタップすると、2回目以降では全時間帯の再検索を行います。

動作イメージ


※ブックマークレットの登録・利用方法が分からない場合は、基本的な使い方のページを参考にしてください

重要

サイト側の処理が変則的な上、本来の処理に極力影響を及ぼさずにブックマークレットの処理を追加しているため、インターセプトも使用し、かなり回りくどい複雑な処理を行っております
サイト側の仕様変更で動作しなくなる可能性があるため、動作しない、挙動がおかしいと感じたらすぐにお知らせください

ブックマークレット文字列

以下の文字列でブックマークレットを登録し、後述の「使い方」に従い、宿泊予約特典でのレストラン空き検索ページで使用してください。

ダミー登録用の空ページのリンク
スマホの場合
iPhone Safari / Chrome および Android Chrome など
ブックマークレット文字列
PCブラウザの場合
以下のリンクボタンを、ブラウザのブックマークバーへドラッグ&ドロップして登録してください

使い方

  1. スマホ向けサイトの「宿泊予約特典」の「レストラン」ページを表示します
  2. スマホ向けサイトのメニューから「予約・購入履歴」を開き、
    「予約・購入履歴一覧」画面で目的の予約の「詳細 / 変更・キャンセル」をタップ→「宿泊予約特典・オプションを追加する」をタップ→「宿泊特典の追加」をタップ→「レストラン」をタップします


  3. レストランの一覧画面(「予定を追加する」画面)が表示されたらこのブックマークレットを呼び出します
    (特にメッセージは表示されません)

  4. レストランを選択し、「人数・時間の選択」画面から「時間帯」をタップし、時間帯別の空き検索結果画面(「時間の選択」画面)を表示します
  5. この画面で、各時間帯(朝食・昼食・夕食)のタイトルをタップすると、その時間帯を再検索し結果を表示します
    ※内部の仕組み上、時間帯別での検索時も画面全体の「読み込み中」画面となります


    「人数・時間の選択」画面で「時間帯」をタップすると、2回目以降は全時間帯を再検索します

ソースコード

ブックマークレット化前のソースコードです
ご自身で表示等カスタマイズされたい方はご自由にご利用ください
※ブックマークレット化の方法については記載していません

JavaScriptコード
コピー
(function () {
  const markingElemId = '__privileges_restaurant_reload';
  if (document.getElementById(markingElemId)) {
    alert('すでに実行されています');
    return;
  };

  if (!document.getElementById('timeContent') || !document.getElementById('timeType')) {
    // 対象外ページ
    alert('このページでは実行できません');
    return;
  };

  const markingElem = document.createElement('div');
  markingElem.id = markingElemId;
  markingElem.style.display = 'none';
  document.body.appendChild(markingElem);

  const getTextNode = ($target) => {
    let result = '';
    $($target).contents().each(function () {
      if (this.nodeType === 3 && /\S/.test(this.data)) {
        result += this.nodeValue;
      };
    });
    return result;
  };

  let opened_headers = [];
  const save_accordion_status = () => {
    opened_headers = [];
    $('#timeContent section.js-accordion header.open h1').each((i, el) => {
      const headerText = getTextNode(el);
      opened_headers.push(headerText);
    });
  };

  // 時間帯別ヘッダをタップしたときに対象時間帯のみをリロード
  const timeRanges = document.querySelectorAll('#timeContent section h1#mealDivName');
  timeRanges.forEach((el_timeRange) => {
    el_timeRange.addEventListener('click', () => {
      save_accordion_status();
      const timeType = $("#timeType").val();
      // まず、親セクションの兄弟要素を取得する
      const el_sections = $(el_timeRange).closest(`section[class$=${timeType}]`).siblings(`section[class$=${timeType}]`);
      el_sections.each((id, el) => {
        // timeTypeのクラスを書き換え
        for (const cls of el.classList) {
          if (cls.endsWith(timeType)) {
            $(el).removeClass(cls).addClass(`__${cls}`);
          };
        };
      });
      const task = controller.getTimeInfo();
      task.done(() => {
        el_sections.each((id, el) => {
          // timeTypeのクラスを書き換え(戻す)
          for (const cls of el.classList) {
            if (cls.startsWith('__')) {
              $(el).removeClass(cls).addClass(cls.replace(/^__/, ''));
            };
          };
        });
      });
    });
    el_timeRange.style.cursor = 'pointer';
  });

  // timeGet.refresh のインターセプト
  const orig_timeGet_refresh = timeGet.refresh;
  timeGet.refresh = function (b, a) {
    if ($(`#timeContent section.${b}`).length) {
      return orig_timeGet_refresh.apply(this, arguments);
    } else {
      const e = $.Deferred();
      e.resolve();
      return e.promise();
    };
  };

  // アコーディオンの状態を復元
  const orig_setupAccordion = setupAccordion;
  setupAccordion = function () {
    // 
    $('#timeContent section.js-accordion header').each((idx, el) => {
      const headerCaption = $(el).find('h1');
      if (opened_headers.includes(getTextNode(headerCaption))) {
        $(el).addClass('open');
      };
    });
    orig_setupAccordion.apply(this, arguments);
  };

  // 「時間の選択」から戻るを押したときに、検索済みフラグをリセット
  // すでに時間を選択している場合を除く
  document.querySelectorAll('#timeContent > header a.cancel, #timeContentMain > ul.listBtn01 a.back').forEach((el) => {
    el.addEventListener('click', () => {
      // 戻るときはアコーディオン状態をリセットする
      opened_headers = [];
      if (!document.querySelector('#timeContent table tr.selected')) {
        timeGet.isSearch = false;
      };
    });
  });
})();