🎯 系列目標:用 30 天時間,從零開始打造一個專屬輔大學生的課表生成 Chrome 擴充功能
👨💻 作者:輔大智慧資安 412580084
📅 Day 10:Chrome Extension 實作篇 - Popup 按鈕事件處理
昨天我們建立了 popup.js 的基礎架構,今天我們要讓按鈕真正具備功能!我們將學習如何處理按鈕點擊事件,並提供使用者回饋。
今天我們要完成:
我們將要對生成課表按鈕添加重複點擊禁用的功能:
// 處理生成課表按鈕點擊
function handleGenerateClick() {
console.log('🔘 生成課表按鈕被點擊');
// 顯示載入狀態
showStatus('正在準備生成課表...', 'info');
// 禁用按鈕防止重複點擊
const generateButton = document.getElementById('generateButton');
generateButton.disabled = true;
generateButton.textContent = '⏳ 處理中...';
// 模擬處理過程(3秒後完成)
setTimeout(() => {
// 恢復按鈕狀態
generateButton.disabled = false;
generateButton.textContent = '📊 開始生成課表';
// 顯示成功訊息
showStatus('課表生成成功!', 'success');
console.log('✅ 課表生成完成');
}, 3000);
}
設定按鈕也與生成課表按鈕一樣:
// 處理設定按鈕點擊
function handleSettingsClick() {
console.log('🔘 設定按鈕被點擊');
showStatus('正在載入設定...', 'info');
// 模擬載入設定(2秒後完成)
setTimeout(() => {
showStatus('設定:自動儲存已開啟', 'success');
// 3秒後回到準備狀態
setTimeout(() => {
showStatus('準備就緒', 'success');
}, 3000);
}, 2000);
}
因為我們在按鈕添加了過度狀態 info
,所以要在showStatus
函數中將原本:
statusDiv.classList.remove('success', 'error');
修改成:
statusDiv.classList.remove('success', 'error', 'info');
然後再將原 if判斷式
改成:
statusDiv.classList.add(type);
function showLoadingStatus(message) {
const statusDiv = document.getElementById('status');
if (statusDiv) {
statusDiv.innerHTML = `${message} <span class="loading">⏳</span>`;
statusDiv.style.display = 'block';
statusDiv.classList.remove('success', 'error');
statusDiv.classList.add('info');
}
}
在 popup.html 的 <style>
區塊中添加新樣式:
.status.info {
background-color: #e3f2fd;
color: #1976d2;
}
.loading {
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
我們會發現生成與設定按鈕在禁用與啟用的程式碼有重複,所以應該要對按鈕狀態封裝以方便管理:
// 設定按鈕載入狀態
function setButtonLoading(buttonId, loadingText) {
const button = document.getElementById(buttonId);
if (button) {
button.disabled = true;
button.dataset.originalText = button.textContent;
button.textContent = loadingText;
}
}
// 恢復按鈕正常狀態
function resetButton(buttonId) {
const button = document.getElementById(buttonId);
if (button) {
button.disabled = false;
button.textContent = button.dataset.originalText || button.textContent;
}
}
使用新的按鈕狀態管理重寫1.1
1.2
事件處理使其更簡潔:
// 改進的生成課表按鈕處理
function handleGenerateClick() {
console.log('🔘 生成課表按鈕被點擊');
// 設定按鈕載入狀態
setButtonLoading('generateButton', '⏳ 處理中...');
// 顯示載入狀態
showLoadingStatus('正在準備生成課表...');
// 模擬處理過程
setTimeout(() => {
// 恢復按鈕狀態
resetButton('generateButton');
// 顯示成功訊息
showStatus('課表生成成功!', 'success');
console.log('✅ 課表生成完成');
}, 3000);
}
// 改進的設定按鈕處理
function handleSettingsClick() {
console.log('🔘 設定按鈕被點擊');
setButtonLoading('settingsButton', '⏳ 載入中...');
showLoadingStatus('正在載入設定...');
setTimeout(() => {
resetButton('settingsButton');
showStatus('設定:自動儲存已開啟', 'success');
setTimeout(() => {
showStatus('準備就緒', 'success');
}, 3000);
}, 2000);
}
更新 popup.js 檔案:
更新 popup.html 的 CSS:
<style>
區塊重新載入擴充功能:
測試按鈕功能:
點擊「開始生成課表」按鈕
觀察按鈕變成「處理中...」並被禁用
等待 3 秒看到成功訊息
檢查 Console 輸出:
📁 fju-schedule-extension/
├── 📄 manifest.json ← 擴充功能設定
├── 📄 background.js ← 背景腳本
├── 📄 popup.html ← 使用者介面(需更新 CSS)
└── 📄 popup.js ← 彈出視窗邏輯(今天完成事件處理)
🔗 知識銜接:今天我們讓按鈕具備了真正的功能和使用者回饋,明天將學習如何讓 popup 與 background script 進行消息傳遞。
🎯 下集預告:Day 11 - Popup 與 Background 消息傳遞 📡