待合室の詳細待ち時間を表示

PC向け/スマホ向けサイト両対応
All-in-One対応

機能概要

待合室での表示が「1時間以上」でも詳細な待ち時間を表示し、順番待ちの進行具合をパーセントで表示します
※推定時間の正確性は変わりません (混雑度の目安にご利用ください)

動作イメージ


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

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

以下の文字列でブックマークレットを登録し、待合室ページで使用してください

ダミー登録用の空ページのリンク
スマホの場合
iPhone Safari / Chrome および Android Chrome など
ブックマークレット文字列
ブックマークのURL欄へ貼り付ける時に、文字が途中で切れてしまう方はこちらをタップ 5000文字以内に圧縮しています
ブックマークレット文字列
PCブラウザの場合
以下のリンクボタンを、ブラウザのブックマークバーへドラッグ&ドロップして登録してください

使い方

詳細な時間を表示させる
  1. 待合室での待機中ページを開く
  2. 通常どおり、予約サイトにアクセスし待合室の待機中ページが表示されたページにします

  3. ブックマークレットを適用
  4. この状態でブックマークを開き、登録したブックマークをタップします

  5. 青文字で順番の進行度と詳細な待ち時間が表示されます
  6. 適用直後は「次回のデータ更新待ち」と表示されますが、そのまま最大40秒経過すると更新されます

追加の機能
待ち状態を他のデバイスに引き継ぐ機能

PCで待合室に待機していたが、外出のためスマホで引き継ぎたい、といったような場合に現在の待ち状態を別の端末やブラウザに引き継ぐことができます。
(この機能は、もともと待合室の機能として備わっているものですが、表示していないサイトもあります)
このブックマークレットを使用するとこの機能が表示されるようになります

  1. 画面下部に小さく「列ID」という場所が表示されているので、それをタップ/クリックします


  2. URLが書かれたダイアログが表示されます(画面省略)
  3. 表示されたURLをコピーし他のデバイスのブラウザで開きます
  4. 待ち状態が引き継がれます
    (画面省略)

注意
待ち状態を引き継ぐためのURLや、「列ID」の右をタップして表示されるIDは他人に開示しないでください

ソースコードおよび処理概要

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

簡単な解説

JavaScriptコード
コピー
javascript: (function (d) {
  if (d.getElementById('expectedServiceTimeActual') || !d.querySelector('span#MainPart_lbExpectedServiceTime')) {
    return;
  };
  const insertAfter = (elem, posElem) => {
    posElem.parentElement.insertBefore(elem, posElem.nextSibling);
  };
  const match = window.queueViewModel.queueViewSession.match(/&sets=(\d+)$/);
  let sets;
  if (match) {
    sets = Number(match[1]);
  };
  const commonCSS = 'text-align:center; font-weight:bold; color:blue; margin-top:10px;';
  let pos1 = d.querySelector('span#MainPart_lbExpectedServiceTimeTimeZonePostfix');
  if (!pos1) {
    pos1 = d.querySelector('span#MainPart_lbExpectedServiceTime');
  };
  const area1 = d.createElement('div');
  area1.setAttribute('id', 'expectedServiceTimeActual');
  area1.style.cssText = commonCSS;
  area1.innerHTML = '(詳細な推定時刻: 次回のデータ更新待ち)';
  insertAfter(area1, pos1);

  const pos2 = d.querySelector('span#MainPart_lbWhichIsIn');
  const area2 = d.createElement('div');
  area2.setAttribute('id', 'whichIsInDetail');
  area2.style.cssText = commonCSS;
  area2.innerHTML = '(詳細な待ち時間: 次回のデータ更新待ち)';
  insertAfter(area2, pos2);

  const pos3 = d.querySelector('div.warning-box');
  const area3 = d.createElement('div');
  area3.setAttribute('id', 'progressPercent');
  area3.style.cssText = `${commonCSS};font-size:16px;`;
  area3.innerHTML = '(進行度: 次回のデータ更新待ち)';
  pos3.append(area3);

  const area4 = d.createElement('div');
  area4.setAttribute('id', 'totalWaitTime');
  area4.style.cssText = commonCSS;
  insertAfter(area4, area2);

  d.querySelector('#footer-direct-link').style.display = 'block';
  const el_id = d.getElementById('hlLinkToQueueTicket2');
  if (el_id) {
    el_id.style.opacity = '0';
    el_id.addEventListener('click', () => {
      el_id.style.opacity = el_id.style.opacity ? '' : '0';
    });
  };

  var origOpen = XMLHttpRequest.prototype.open;
  XMLHttpRequest.prototype.open = function () {
    const dateFormat = (date, format) => {
      const _fmt = {
        hh: date => { return ('0' + date.getHours()).slice(-2) },
        mm: date => { return ('0' + date.getMinutes()).slice(-2) },
        ss: date => { return ('0' + date.getSeconds()).slice(-2) },
        dd: date => { return ('0' + date.getDate()).slice(-2) },
        yyyy: date => { return date.getFullYear() + '' },
        MM: date => { return ('0' + (date.getMonth() + 1)).slice(-2) },
      };
      const _priority = ['dd', 'yyyy', 'MM', 'hh', 'mm', 'ss'];
      return _priority.reduce((res, fmt) => res.replace(fmt, _fmt[fmt](date)), format);
    };
    const getHMS = (total_sec) => {
      const hours = Math.floor(total_sec / 60 / 60);
      const minutes = Math.floor((total_sec - hours * 60 * 60) / 60);
      const seconds = Math.floor(total_sec - (hours * 60 + minutes) * 60);
      return [hours, minutes, seconds]
    };

    this.addEventListener('load', () => {
      const expectedServiceTimeActual = d.getElementById("expectedServiceTimeActual");
      const whichIsInDetail = d.getElementById("whichIsInDetail");
      const progressPercent = d.getElementById("progressPercent");
      const totalWaitTime = d.getElementById("totalWaitTime");
      try {
        const now = new Date();
        const res = JSON.parse(this.responseText);
        const isRedirectToTarget = res.isRedirectToTarget;
        let mod_progress;
        if (res.ticket) {
          const { progress, expectedServiceTimeUTC, lastUpdatedUTC, queuePaused } = res.ticket;
          const expectTime = new Date(expectedServiceTimeUTC);
          const [hours, minutes, seconds] = getHMS((expectTime - now) / 1000);
          mod_progress = progress;
          const fontColor = hours >= 2 ? 'red' : 'blue';
          expectedServiceTimeActual.style.color = fontColor;
          whichIsInDetail.style.color = fontColor;

          if (progress < 1) {
            expectedServiceTimeActual.innerHTML = `${dateFormat(expectTime, 'yyyy/MM/dd hh:mm:ss')}`;
            whichIsInDetail.innerHTML = (hours ? `${hours} 時間 ` : '') + `${minutes} 分 ${seconds} 秒`;
          } else {
            expectedServiceTimeActual.innerHTML = '';
            whichIsInDetail.innerHTML = '';
          };
        };

        if (isRedirectToTarget) {
          mod_progress = 1;
        };

        if (sets) {
          const [total_hours, total_minutes, total_seconds] = getHMS((now.getTime() - sets) / 1000);
          const fontColor = total_hours >= 1 ? 'red' : 'blue';
          totalWaitTime.style.fontWeight = 'normal';
          totalWaitTime.innerHTML = `ここまでの合計待ち時間:<br><span style="color:${fontColor};font-weight:bold;">${total_hours} 時間 ${total_minutes} 分 ${total_seconds} 秒</span>`;
        };

        progressPercent.innerHTML = `進行度: ${(mod_progress * 100).toFixed()}%25`;
      } catch (err) {
      }
    });
    origOpen.apply(this, arguments);
  };
})(document);