Chắc chắn có rất nhiều bạn sử dụng thư viện hoặc plugin để tạo datepicker như jQuery, Boostrap,… Nhưng bạn cũng hiểu được rằng chúng ta sẽ không dùng hết tính năng trong thư viện/plugin đó gây ra lãng phí tài nguyên. Vì vậy trong bài viết này sharescript sẽ hướng dẫn cách tạo datepicker chỉ sử dụng css và javascript.
Mình đã nén source và chia sẻ ở link download cuối bài viết, bạn có thể cuộn xuống dưới tải code về trước sau đó đọc bài viết để dễ hiểu hơn.
Tạo datepicker đơn giản
1] Tạo file index.html
Date Picker OptionsDate Picker Options
window.addEventListener["load", function[]{ picker.attach[{ target: "input-opt", container: "pick-opt", disableday : [2, 7], // DISABLE TUE, SUN startmon: true // WEEK START ON MON }]; }];
2] Tạo file dp-dark.css
/* [A] POPUP */ .picker-wrap { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba[0,0,0,0.5]; opacity: 0; visibility: hidden; transition: opacity 0.2s; } .picker-wrap.show { opacity: 1; visibility: visible; } .picker-wrap .picker { margin: 50vh auto 0 auto; transform: translateY[-50%]; } /* [B] CONTAINER */ .picker { max-width: 300px; border: 1px solid #000; background: #444; padding: 10px; } /* [C] MONTH + YEAR */ .picker-m, .picker-y { width: 50%; padding: 5px; box-sizing: border-box; font-size: 16px; } /* [D] DAY */ .picker-d table { color: #fff; border-collapse: separate; width: 100%; margin-top: 10px; } .picker-d table td { width: 14.28%; /* 7 EQUAL COLUMNS */ padding: 5px; text-align: center; } /* HEADER CELLS */ .picker-d-h td { font-weight: bold; } /* BLANK DATES */ .picker-d-b { background: #4e4e4e; } /* TODAY */ .picker-d-td { background: #d84f4f; } /* PICKABLE DATES */ .picker-d-d:hover { cursor: pointer; background: #a33c3c; } /* UNPICKABLE DATES */ .picker-d-dd { color: #888; background: #4e4e4e; }
3] Tạo file datepicker.js
var picker = { // [A] ATTACH DATEPICKER TO TARGET // target : datepicker will populate this field // container : datepicker will be generated in this container // startmon : start on Monday [default false] // disableday : array of days to disable, e.g. [2,7] to disable Tue and Sun attach : function [opt] { // [A1] CREATE NEW DATEPICKER var dp = document.createElement["div"]; dp.dataset.target = opt.target; dp.dataset.startmon = opt.startmon ? "1" : "0"; dp.classList.add["picker"]; if [opt.disableday] { dp.dataset.disableday = JSON.stringify[opt.disableday]; } // [A2] DEFAULT TO CURRENT MONTH + YEAR - NOTE: UTC+0! var today = new Date[], thisMonth = today.getUTCMonth[], // Note: Jan is 0 thisYear = today.getUTCFullYear[], months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; // [A3] MONTH SELECT var select = document.createElement["select"], option = null; select.classList.add["picker-m"]; for [var mth in months] { option = document.createElement["option"]; option.value = parseInt[mth] + 1; option.text = months[mth]; select.appendChild[option]; } select.selectedIndex = thisMonth; select.addEventListener["change", function[]{ picker.draw[this]; }]; dp.appendChild[select]; // [A4] YEAR SELECT var yRange = 10; // Year range to show, I.E. from thisYear-yRange to thisYear+yRange select = document.createElement["select"]; select.classList.add["picker-y"]; for [var y = thisYear-yRange; y < thisYear+yRange; y++] { option = document.createElement["option"]; option.value = y; option.text = y; select.appendChild[option]; } select.selectedIndex = yRange; select.addEventListener["change", function[]{ picker.draw[this]; }]; dp.appendChild[select]; // [A5] DAY SELECT var days = document.createElement["div"]; days.classList.add["picker-d"]; dp.appendChild[days]; // [A6] ATTACH DATE PICKER TO TARGET CONTAINER + DRAW THE DATES picker.draw[select]; // [A6-I] INLINE DATE PICKER if [opt.container] { document.getElementById[opt.container].appendChild[dp]; } // [A6-P] POPUP DATE PICKER else { // [A6-P-1] MARK THIS AS A "POPUP" var uniqueID = 0; while [document.getElementById["picker-" + uniqueID] != null] { uniqueID = Math.floor[Math.random[] * [100 - 2]] + 1; } dp.dataset.popup = "1"; dp.dataset.dpid = uniqueID; // [A6-P-2] CREATE WRAPPER var wrapper = document.createElement["div"]; wrapper.id = "picker-" + uniqueID; wrapper.classList.add["picker-wrap"]; wrapper.appendChild[dp]; // [A6-P-3] ATTACH ONCLICK TO SHOW/HIDE DATEPICKER var target = document.getElementById[opt.target]; target.dataset.dp = uniqueID; target.readOnly = true; // Prevent onscreen keyboar on mobile devices target.onfocus = function [] { document.getElementById["picker-" + this.dataset.dp].classList.add["show"]; }; wrapper.addEventListener["click", function [evt] { if [evt.target.classList.contains["picker-wrap"]] { this.classList.remove["show"]; } }]; // [A6-P-4] ATTACH POPUP DATEPICKER TO BODY document.body.appendChild[wrapper]; } }, // [B] DRAW THE DAYS IN MONTH // el : HTML reference to either year or month selector draw : function [el] { // [B1] GET DATE PICKER COMPONENTS var parent = el.parentElement, year = parent.getElementsByClassName["picker-y"][0].value, month = parent.getElementsByClassName["picker-m"][0].value, days = parent.getElementsByClassName["picker-d"][0]; // [B2] DATE RANGE CALCULATION - NOTE: UTC+0! var daysInMonth = new Date[Date.UTC[year, month, 0]].getUTCDate[], startDay = new Date[Date.UTC[year, month-1, 1]].getUTCDay[], // Note: Sun = 0 endDay = new Date[Date.UTC[year, month-1, daysInMonth]].getUTCDay[], startDay = startDay==0 ? 7 : startDay, endDay = endDay==0 ? 7 : endDay; // [B3] GENERATE DATE SQUARES [IN ARRAY FIRST] var squares = [], disableday = null; if [parent.dataset.disableday] { disableday = JSON.parse[parent.dataset.disableday]; } // [B4] EMPTY SQUARES BEFORE FIRST DAY OF MONTH if [parent.dataset.startmon=="1" && startDay!=1] { for [var i=1; i