javascript

網頁

使用 JS 實做分頁

參考 Laravel 5 的分頁模式,11 頁以下全部顯示,12 頁以上會出現省略的點點記號。

const page = document.querySelector('#page');

const pageNum = 16;

const urlParams = new URLSearchParams(window.location.search);

const activePage = urlParams.get('page');
console.log('activePage:', activePage);

// 顯示頁數 11 以下
if (pageNum <= 11) {
  let data = '';

  for (let i = 1; i <= pageNum; i++) {
    data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
  }

  page.innerHTML = data;
}

// 顯示頁數 12 以上
if (pageNum > 11) {
  let data = '';

  if (activePage < 7) {
    for (let i = 1; i <= pageNum; i++) {
      if (i <= 8) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
      }

      if (i === pageNum - 2) {
        data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
      }

      if (i === pageNum - 1) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum - 1}">${pageNum - 1}</a></li>`;
      }

      if (i === pageNum) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum}">${pageNum}</a></li>`;
      }
    }
  }

  if (activePage >= 7 && Number(activePage) + 6 <= pageNum) {
    for (let i = 1; i <= pageNum; i++) {
      if (i === 1 || i === 2) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
      }

      if (i === 3) {
        data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
      }

      if (i >= activePage - 3 && i <= Number(activePage) + 3) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
      }

      if (i === pageNum - 2) {
        data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
      }

      if (i === pageNum - 1) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum - 1}">${pageNum - 1}</a></li>`;
      }

      if (i === pageNum) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${pageNum}">${pageNum}</a></li>`;
      }
    }
  }

  if (activePage >= 7 && Number(activePage) + 6 > pageNum) {
    for (let i = 1; i <= pageNum; i++) {
      if (i === 1 || i === 2) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
      }

      if (i === 3) {
        data += `<li class="page-item"><a class="page-link" href="javascript:;">...</a></li>`;
      }

      if (i >= pageNum - 8) {
        data += `<li class="page-item"><a class="page-link" href="/?page=${i}">${i}</a></li>`;
      }
    }
  }

  page.innerHTML = data;
}

Demo

網頁

[JS] Simple Calendar

參考 Learn How to Code a Simple JavaScript Calendar and Datepicker 這篇教學,做了一個簡單的月曆。

const previousMonth = document.querySelector('.previous-month');
const nextMonth = document.querySelector('.next-month');
const yearMonth = document.querySelector('.year-month');
const day = document.querySelector('.day');

let today = new Date();

// returns the full year of a date
// 4 digits
let year = today.getFullYear();

// returns the month (0 to 11) of a date
let month = today.getMonth();

showCalendar();

// 上個月
previousMonth.addEventListener('click', (e) => {
  e.preventDefault();

  month--;

  if (month < 0) {
    year--;
    month = 11;
  }

  showCalendar();
});

// 下個月
nextMonth.addEventListener('click', (e) => {
  e.preventDefault();

  month++;

  if (month > 11) {
    year++;
    month = 0;
  }

  showCalendar();
});

// function
function showCalendar() {
  yearMonth.innerHTML = `${year} / ${month + 1}`;

  // 當月第一天
  const firstDay = new Date(year, month, 1);

  // returns the day of the week (0 to 6) of a date
  // Sunday = 0, Monday = 1, ....
  const firstDayIndex = firstDay.getDay();

  // 當月最後一天
  const lastDay = new Date(year, month + 1, 0);

  // returns the day of the month (1 to 31) of a date
  const daysInMonth = lastDay.getDate();

  let dayHtml = '';

  for (let i = 1; i <= 42; i++) {
    if (i < firstDayIndex + 1) {
      dayHtml += '<div></div>';
    } else if (i > firstDayIndex + daysInMonth) {
      break;
    } else {
      const dayNumber = i - firstDayIndex;

      if (
        year === new Date().getFullYear() &&
        month === new Date().getMonth() &&
        dayNumber === new Date().getDate()
      ) {
        dayHtml += `<div class="current-date">${dayNumber}</div>`;
      } else {
        dayHtml += `<div>${dayNumber}</div>`;
      }
    }
  }

  day.innerHTML = dayHtml;
}

Demo

網頁

[JS] 日期

取得格式為 YYYY-MM-DD 的今天日期。

下面是問 ChatGPT 的結果:

const today = new Date();

const year = today.getFullYear();

// 月份從 0 開始,所以要加 1,並確保兩位數
const month = String(today.getMonth() + 1).padStart(2, '0');

// 確保日期為兩位數
const day = String(today.getDate()).padStart(2, '0');

const formattedDate = `${year}-${month}-${day}`;

// 2024-05-23
console.log(formattedDate);

在網路上還看到其他方式:

const today = new Date();

const year = today.getFullYear();
const month = ('0' + (today.getMonth() + 1)).slice(-2);
const date = ('0' + today.getDate()).slice(-2);

const hours = ('0' + today.getHours()).slice(-2);
const minutes = ('0' + today.getMinutes()).slice(-2);
const seconds = ('0' + today.getSeconds()).slice(-2);

// 2024-05-23 10:55:11
console.log(`${year}-${month}-${date} ${hours}:${minutes}:${seconds}`);

———

取得最近七天日期。

下面是問 ChatGPT 的結果:

const today = new Date();

for (let i = 0; i < 7; i++) {
  const tempDate = new Date();

  // 設定日期為今天減去 i 天
  tempDate.setDate(today.getDate() - i);

  const year = tempDate.getFullYear();

  // 月份從 0 開始,所以要加 1,並確保兩位數
  const month = String(tempDate.getMonth() + 1).padStart(2, '0');

  // 確保日期為兩位數
  const day = String(tempDate.getDate()).padStart(2, '0');

  const formattedDate = `${year}-${month}-${day}`;
  
  console.log(formattedDate);
}

在網路上看到的方式:

const today = new Date();

for (let i = 0; i < 7; i++) {
  const newDate = new Date(today.getTime() - i * 24 * 60 * 60 * 1000);
  
  const year = newDate.getFullYear();
  const month = String(newDate.getMonth() + 1).padStart(2, '0');
  const day = String(newDate.getDate()).padStart(2, '0');
  
  const formattedDate = `${year}-${month}-${day}`;
  
  console.log(formattedDate);
}


其他參考連結:

網頁

[JS] Promise 亮燈

三秒後亮紅燈,二秒後亮綠燈,一秒後亮黃燈,反覆執行。

// 回傳 promise
function lightPromise(second, light) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(light);
    }, second * 1000);
  });
}

function main() {
  const redPromise = lightPromise(3, '[red]'); // 回傳紅燈 promise

  redPromise
    .then((light) => {
      console.log(light, new Date()); // 亮紅燈

      return lightPromise(2, '[green]'); // 回傳綠燈 promise
    })
    .then((light) => {
      console.log(light, new Date()); // 亮綠燈

      return lightPromise(1, '[yellow]'); / 回傳黃燈 promise
    })
    .then((light) => {
      console.log(light, new Date()); // 亮黃燈
      console.log('---------');
      main(); // 再次執行
    });
}

Demo
https://www.yuantw.com/demo/js-promise-light/


參考連結:

網頁

[JS] Throttle

簡單的版本:

let timeoutId;

btn.addEventListener('click', function (e) {
  if (!timeoutId) {
    console.log(new Date()); // 要執行的動作

    timeoutId = setTimeout(() => {
      timeoutId = null; // reset
    }, 1000);
  }
});

Demo
https://www.yuantw.com/demo/js-throttle-1/

———

Function 版:

function throttle(fn, delay = 1000) {
  let timeoutId;

  return function () {
    let context = this;
    let args = arguments;

    if (!timeoutId) {
      fn.apply(context, args);

      timeoutId = setTimeout(() => {
        timeoutId = null;
      }, delay);
    }
  };
}

function show(e) {
  console.log(`${e.target.dataset.text} --`, new Date());
}

Demo
https://www.yuantw.com/demo/js-throttle-2/

返回頂端