/ PROJECT

투두리스트 Chrome Extension (3) - 학습용 스톱워치 그리고 공부시간 수정하기

구현 아이디어

  1. start 버튼 addEventListener에서 click Event 발생시 startTimer() 함수 실행
  • 이 때, 다른 버튼 비활성화
  • 타이머의 경우, Date.now()를 활용해 mileseconds 값을 Hh:Mm:Ss로 변환
  1. 스톱워치 중지 시, Dropdown list에 등록된 할 일 중에 하나를 선택
  • change Event 발생 시, 해당 option의 id를 local storage에 저장
  • 추가 버튼 click Event 발생 시, local storage에서 id 비교 후 공부시간 수정
  1. 화면에서 나갈 경우
  • onbeforeunload Event를 통해, 나가는 시간 local storage에 저장
  • 웹 켜졌을 경우, 현재 시간과 차이 계산해서 시간 수정 후 화면에 표시

예상 구현 결과

  • 공부 하는 시간 측정하는 스톱워치
  • 등록되있는 할 일 중에 선택해서 공부시간 추가하기
  • 화면에서 나가더라도 스톱워치 유지하기

Rate-Determining Step (걸림돌)

Line: 54;
function totalUsageTimeEdit(event) {}

Dropdown list에서 할 일을 선택하는 순간, 바로 시간이 수정되는 것이 아니라 시간 수정 버튼을 눌렀을 경우에 시간이 수정되어야 된다. 이 때 dropdown list에서 submit event가 일어났을 때 정보를 받으려고 하니 list element 전부가 받아와져서 dropdown list에서 option의 id를 가져오는 데 어려움이 있었다.
Local Storage에 잠깐 dropdown list element의 id를 저장했다가 submit할 때 받는 형식으로 해결해봤다.

Line: 54;
function totalUsageTimeEdit(event) {}

Line: 77;
function totalUsageTimeToSeconds(timeData) {}

Line: 87;
function secondsToHhMmSs(inputTime) {}

공부 시간을 기존 데이터에서 추가하는 과정에 있어서 String으로 표현된 시간을 수정하는 과정에서 전부 seconds로 바꿨다가 다시 string으로 전달하는 과정에서 코드의 실수가 꽤 잦았다.

구현 코드

const timer = document.querySelector("h3#timer");
const startButton = document.querySelector("#start-timer");
const resetButton = document.querySelector("#reset-timer");
const pauseButton = document.querySelector("#pause-timer");
const totalTimeAddButtonInTimer = document.querySelector("#timeadd-button");
const timeForm = document.querySelector("#totaltime-submit");
const targetItem_ToAddTime = document.querySelector("#subject-select");
const timeData = document.querySelector("#timer");

// timer 부터 시작하면 됨
let startTime = 0;
let endTime = 0;
let select_SubjectId = 0;

let toDos_InTimer = []; // 여기서 매번 초기화를 시키기 때문에 아래에서 다시 데이터를 받아와야함!!

const INSTANT_SUBJECTID = "instantSubjectId";
const TODOS_KEY_TIMEEDIT = "todos";

function startTimer() {
  startButton.disabled = true;
  totalTimeAddButtonInTimer.disabled = true;
  resetButton.disabled = true;
  if (!startTime) {
    startTime = Date.now(); // 처음 시작할 때
  } else {
    startTime += Date.now() - endTime; // 재시작할 때
  }
  continueTimer = setInterval(function () {
    let nowTime = Math.floor((Date.now() - startTime) / 1000);
    timer.innerText = secondsToHhMmSs(nowTime);
  }, 1000);
}

function pauseTimer() {
  startButton.disabled = false;
  totalTimeAddButtonInTimer.disabled = false;
  resetButton.disabled = false;
  if (continueTimer) {
    clearInterval(continueTimer);
    endTime = Date.now(); // STOP시점의 시간 저장
  }
}

function resetTimer() {
  startButton.disabled = false;
  totalTimeAddButtonInTimer.disabled = false;
  timer.innerText = "00:00:00";
  startTime = 0;
}

function totalUsageTimeEdit(event) {
  event.preventDefault();
  const targetSubjectId = localStorage.getItem(INSTANT_SUBJECTID);
  const targetSubjectId_toInteger = parseInt(targetSubjectId);
  const thisTotalUsageTime = totalUsageTimeToSeconds(timeData.innerText);
  const toDoData = localStorage.getItem(TODOS_KEY_TIMEEDIT);
  const parsedToDos = JSON.parse(toDoData);
  toDos_InTimer = parsedToDos;
  parsedToDos.forEach(function (obj) {
    if (obj.id === targetSubjectId_toInteger) {
      const beforeEditTime = totalUsageTimeToSeconds(obj.total_usage_time);
      const nowEditTime = totalUsageTimeToSeconds(timeData.innerText);
      const totalEditTime = beforeEditTime + nowEditTime;
      const calculateTotalEditTime = secondsToHhMmSs(totalEditTime);
      obj.total_usage_time = calculateTotalEditTime;
    }
  });
  localStorage.setItem(TODOS_KEY_TIMEEDIT, JSON.stringify(parsedToDos));
  timer.innerText = "00:00:00";
  startTime = 0;
  //  테이블에 다시 그리기
}

function totalUsageTimeToSeconds(timeData) {
  let timeArray = timeData.split(":");
  const hh = parseInt(timeArray[0]);
  const mm = parseInt(timeArray[1]);
  const ss = parseInt(timeArray[2]);
  let usageTime_toSeconds = 0;
  usageTime_toSeconds = hh * 3600 + mm * 60 + ss;
  return usageTime_toSeconds;
}

function secondsToHhMmSs(inputTime) {
  let hours = String(Math.floor(inputTime / 3600)).padStart(2, "0");
  let minutes = String(Math.floor((inputTime - 3600 * hours) / 60)).padStart(
    2,
    "0"
  );
  let seconds = String(inputTime - 3600 * hours - 60 * minutes).padStart(
    2,
    "0"
  );
  const HhMmSs = hours + ":" + minutes + ":" + seconds;
  return HhMmSs;
}

function saveTargetSubjectId_ToAddTime() {
  const selectSubjectId =
    targetItem_ToAddTime.options[targetItem_ToAddTime.selectedIndex].id;
  select_SubjectId = selectSubjectId;
  localStorage.setItem(INSTANT_SUBJECTID, select_SubjectId);
}

startButton.addEventListener("click", startTimer);
pauseButton.addEventListener("click", pauseTimer);
resetButton.addEventListener("click", resetTimer);
timeForm.addEventListener("submit", totalUsageTimeEdit);
targetItem_ToAddTime.addEventListener("change", saveTargetSubjectId_ToAddTime);