iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Modern Web

Modern Web × AI《拖延怪日記》:語錄陪伴擺脫拖延系列 第 18

【Day 18】— 入門 JavaScript 網頁架設:navigator.share(溫暖總結與分享引導)

  • 分享至 

  • xImage
  •  

摘要
完成任務排程後,立刻在頁面上生成一句溫暖總結:「你選擇在【下午】安排了《任務》…」,並提供兩個行動按鈕:分享挑戰給好友與查看我的假日紀錄。學會把「先前表單選擇 + 拖曳結果」組合成動態文案,並綁定新按鈕事件(分享/跳轉歷史)。

為什麼要加「溫暖總結」與分享引導?

  • 心理收束:把剛做的決定用一句話明白寫出來,讓行動有「完成感」和記憶點。
  • 社會支持:一鍵分享挑戰,能得到朋友回饋或一起做,提升持續率。
  • 回顧動線:引導進歷史頁,促進自我觀察(常在哪個時段最有效?)。

學習重點

  • 動態文本:把 SCHEDULE_KEY 的時段 + 最新任務名稱組成總結句。
  • 新事件綁定:navigator.share(可用時)或 複製文案 fallback;以及一鍵跳轉 showPage('history')。
  • 即時更新:在 placeTaskTo() 與安排頁顯示時觸發渲染。

核心流程

  1. HTML:在任務安排區塊加一段「總結文字」與兩顆新按鈕。
  2. 工具函式:依 recordId 取得任務文字。
  3. 渲染函式:讀取 SCHEDULE_KEY 與最新任務,拼出「你選擇在【時段】安排了《任務》…」。
  4. 事件:
    • 在 placeTaskTo() 成功後呼叫 renderArrangementSummary()。
    • 在進入安排頁(showPage('taskSchedule'))時也呼叫一次,確保重整後還能看到。
    • 綁定分享與歷史跳轉按鈕。

實作

假設已具備:

  • Day 4–5 → readRecords / writeRecords / addRecord(紀錄存取)
    ‧ 讀任務文字(getTaskTitleById 內用 readRecords);新增任務仍走 addRecord。
  • Day 12 → showPage(頁面切換骨架)
    ‧ 「查看我的假日紀錄」→ showPage('history');進入安排頁時由 showPage('taskSchedule') 觸發渲染與總結。
  • Day 13 → onSubmit(新增紀錄來源)
    ‧ 仍是最新任務的產生點,Day 18 的總結會抓「最新紀錄 + 已排時段」。
  • Day 14 → PERIOD_LABEL(顯示用 label)
    ‧ 總結句「你選擇在【下午】…」與分享文案用 PERIOD_LABEL[period]。
  • Day 15 → btnStartNow click handler(分支導流到安排頁)
    ‧ 由此進入 taskSchedule,Day 18 在該頁顯示溫暖總結與分享按鈕。
  • Day 16 → SCHEDULE_KEY / readScheduleMap / writeScheduleMap / renderTaskCard / placeTaskTo(任務安排狀態與渲染)
  • Day 17 → DnD 綁定(dragover drop 內最後仍呼叫 placeTaskTo(period))
    ‧ 透過拖曳完成安排後,同樣由 placeTaskTo 觸發 Day 18 的總結更新。
  1. HTML:安排頁新增「溫暖總結 + 兩顆按鈕」
    請在 #taskScheduleSection 中,<p id="scheduleFeedback"> 下方加入以下內容:
<!-- [Day18-NEW] 溫暖總結與分享引導 -->
<p id="arrangementSummary" aria-live="polite" style="margin-top:.25rem;"></p>
<div id="postArrangeActions" style="display:flex; gap:.5rem; margin-top:.5rem;">
  <button id="btnShare" type="button">分享挑戰給好友</button>
  <button id="btnViewMyHistory" type="button" aria-controls="historySection">查看我的假日紀錄</button>
</div>
  1. JS:工具函式(依 id 找任務名稱)
    放在「讀寫紀錄」區塊附近即可:
// [Day18-NEW] 依 recordId 取得任務文字
function getTaskTitleById(id) {
  if (!id) return '';
  const list = readRecords();
  const rec = list.find(r => r.id === id);
  return rec ? rec.task : '';
}
  1. JS:渲染「溫暖總結」
    可放在 renderTaskCard() 附近,或安排頁相關函式下方:
// [Day18-NEW] 溫暖總結渲染:你選擇在【下午】安排了《任務》…
function renderArrangementSummary() {
  const summaryEl = document.getElementById('arrangementSummary');
  if (!summaryEl || !currentTaskId) return;

  const map = readScheduleMap();
  const period = map[currentTaskId];               // 'morning' | 'afternoon' | 'evening' | undefined
  const task   = getTaskTitleById(currentTaskId);  // 任務名稱
  if (!period || !task) {
    summaryEl.textContent = ''; // 尚未安排或尚無任務
    return;
  }
  summaryEl.textContent = `你選擇在【${PERIOD_LABEL[period] || period}】安排了《${task}》— 給自己一個小小起點吧!`;
}
  1. JS:在「安排成功」與「顯示安排頁」時觸發渲染

(A) 調整 placeTaskTo():在最後一行後面補呼叫

// ★ 原來最後一行:scheduleFeedback.textContent = `已安排到:${PERIOD_LABEL[period] || period}`;
renderArrangementSummary(); // [Day18-NEW] 安排成功後立刻更新總結

(B) 調整 showPage('taskSchedule') 分支:在 renderTaskCard() 後面補一行

renderTaskCard();
renderArrangementSummary(); // [Day18-NEW] 進入安排頁就更新(支援重整後顯示)
  1. JS:新按鈕事件(分享/跳轉歷史)
    加入在其他事件綁定群附近:
// [Day18-NEW] 分享與查看歷史
const btnShare = document.getElementById('btnShare');
const btnViewMyHistory = document.getElementById('btnViewMyHistory');

btnShare?.addEventListener('click', async () => {
  const map = readScheduleMap();
  const period = map[currentTaskId];
  const task   = getTaskTitleById(currentTaskId);
  if (!period || !task) {
    alert('先把任務排到一個時段吧!');
    return;
  }
  const text = `我把《${task}》安排在今天的【${PERIOD_LABEL[period]}】要完成,你也一起來挑戰吧!`;
  const shareData = {
    title: '我的小挑戰',
    text,
    url: location.href // 或你的作品頁 URL
  };
  try {
    if (navigator.share) {
      await navigator.share(shareData);
    } else if (navigator.clipboard?.writeText) {
      await navigator.clipboard.writeText(`${text}\n${location.href}`);
      alert('已複製分享內容到剪貼簿,去貼給好友吧!');
    } else {
      prompt('複製這段內容分享給好友:', `${text}\n${location.href}`);
    }
  } catch (err) {
    console.warn('分享動作被取消或失敗:', err);
  }
});

btnViewMyHistory?.addEventListener('click', () => {
  showPage('history');
});

驗證

  1. 完成排程後顯示總結:把卡片拖到「🧠 下午」,下方出現「你選擇在【下午】安排了《任務》— 給自己一個小小起點吧!」。

  2. 重整後仍存在:重新整理 → 進入安排頁 → 仍能看到同一句總結(因 SCHEDULE_KEY 與最新紀錄存在)。

  3. 分享:按「分享挑戰給好友」:

  4. 桌面瀏覽器若支援 navigator.share → 開啟系統分享面板。
    https://ithelp.ithome.com.tw/upload/images/20250902/201779139aX7bAYTa9.png

  5. 不支援時 → 自動複製文案(或彈出可複製視窗)。

  6. 查看歷史:按「查看我的假日紀錄」→ 成功跳到歷史頁。

怎麼用手機測試分享功能?

  1. 註冊 ngrok:https://ngrok.com/

  2. 登入後選擇 Set up & Installation,可選 HomeBrew 安裝(若有 HomeBrew)或 Download
    https://ithelp.ithome.com.tw/upload/images/20250902/20177913VFtkAojPYK.png

  3. 安裝後複製官網的第二個指令到終端機連接 token

  4. 在終端機運行第三個官網指令,成功會出現以下畫面:
    https://ithelp.ithome.com.tw/upload/images/20250902/20177913aYCcCFJFQg.png

  5. 在手機上開啟紅色底線的 ngrok 公開網址,測試分享功能
    https://ithelp.ithome.com.tw/upload/images/20250902/20177913HoMaLgjMST.jpg

常見錯誤 & 排查

  1. 總結不顯示
    檢查有無最新紀錄:getLatestRecord() 是否回傳 null。
    SCHEDULE_KEY 是否有 currentTaskId 的對應時段。
    確認在 placeTaskTo() 與 showPage('taskSchedule') 都有呼叫 renderArrangementSummary()。
  2. 分享沒反應
    桌面(或特定瀏覽器)不支援 navigator.share:應走剪貼簿 / prompt fallback。
    在 HTTPS 或本機 localhost 測試更穩定(部分 API 在非安全環境受限)。
  3. 任務名稱顯示為空
    getTaskTitleById(currentTaskId) 找不到對應:可能是 currentTaskId 變動或紀錄被刪除;重新新增一筆再試。

上一篇
【Day 17】- 入門 JavaScript 網頁架設:Drag & Drop API(拖曳互動)
下一篇
【Day 19】— 入門 JavaScript 網頁架設:狀態追蹤(再次造訪的互動)
系列文
Modern Web × AI《拖延怪日記》:語錄陪伴擺脫拖延19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言