ساخت انتخابگر تاریخ در جاوا اسکریپت — از صفر تا صد
اغلب ما فکر میکنیم که ساخت یک انتخابگر تاریخ کار سختی است. در این مقاله نشان میدهیم که ساخت انتخابگر تاریخ در جاوا اسکریپت و ریاکت کار بسیار سادهای است. این کار را به کمک شیء داده جاوا اسکریپت انجام میدهیم. ما از Moment.js یا هیچ کتابخانه مشابه دیگر برای تولید تاریخ برای انتخابگر تاریخ استفاده نخواهیم کرد. محصول نهایی چیزی مانند زیر خواهد بود:
کارکرد انتخابگر تاریخ
انتخابگر تاریخی که میخواهیم بسازیم کارکردی به شرح زیر خواهد داشت:
- به صورت پیشفرض یک ورودی (Input) خواهد بود که از قبل با Date پر شده است.
- زمانی که روی ورودی کلیک شود، انتخابگر تاریخ (Date Picker) باز میشود.
- انتخابگر تاریخ شامل دکمههای سال و ماه برای حرکت در میان سالها و ماههای مختلف است.
- در زیر بخش انتخاب ماه، یک شبکه از روزها نمایش خواهد یافت.
- اگر روی روزها کلیک کنیم، انتخابگر تاریخ پنهان میشود و یک timestamp از روزی که کلیک کردهایم در تابع موفقیت (success) ارسالی به انتخابگر تاریخ دریافت خواهیم کرد.
این کلیات انتخابگر تاریخ ساده ما خواهد بود.
ما چندان با کارکردها و API-ها درگیر نمیشویم. این کار عامدانه صورت گرفته است تا همه چیز ساده مانده و درک آن آسانتر باشد. ما صرفاً کد مرکزی انتخابگر تاریخ را مینویسیم، زمانی که این هسته مرکزی را درک کنید، میتوانید هر چیزی که میخواهید از روی آن بسازید.
راهاندازی اپلیکیشن اولیه
پیکربندی Webpack برای این اپلیکیشن مقدماتی، صرفاً هدر دادن زمان محسوب میشود. بدین ترتیب از یک ماژول عالی node به نام create-react-app که از سوی فیسبوک ارائه شده، استفاده میکنیم و نسخه اولیه اپلیکیشن ری اکت خود را میسازیم.
زمانی که اپلیکیشن را با استفاده از اسکریپت فوق ساختیم، به پوشه App میرویم و دستور npm start را وارد میکنیم تا یک سرور لوکال اجرا شود. بدین ترتیب میتوانیم با مراجعه به آدرس http://127.0.0.1:3000 در مرورگر به آن دسترسی پیدا کنیم.
~/> npx create-react-app my-date-picker ~/> ... ~/> ... ~/> ... ~/> cd my-date-picker ~/my-date-picker/> npm start
بدین ترتیب یک وب اپلیکیشن قالبی با لوگوی بزرگ ریاکت در مرورگر خود مشاهده خواهید کرد. اکنون زمان آن رسیده است که کامپوننت خودمان را بسازیم.
انتخابگر تاریخ
ابتدا یک دایرکتوری به نام MyDatePicker ایجاد میکنیم و درون آن دو فایل به نامهای MyDatePicker.js و MyDatePicker.css میسازیم در فایل MyDatePicker.js یک کامپوننت پایهای ریاکت میسازیم و Input از نوع Date را بازگشت میدهیم. همچنین یک Container Div به نام DatePicker که درون Parent Div در تابع رندر قرار گرفته است، بازگشت میدهیم. ساختار فایل ما به صورت زیر است:
Parent Div: این بیرونیترین Div است که همه چیز درون آن قرار میگیرد.
Container Div: این Div شامل انتخابگر تاریخ است و تنها زمانی که روی ورودی کلیک شود ظاهر خواهد شد.
Input: سه هدف دارد. هدف اول آن است که تاریخ انتخابی را نمایش دهد، هدف دیگر آن است که یک رویداد برای باز کردن انتخابگر تاریخ صادر کند و هدف آخر نیز این است که بتوانیم با وارد کردن تاریخ، آن را تغییر دهیم. عنصر ورودی با نوع Date دارای یک DatePicker داخلی است، اما به کمک CSS آن را غیرفعال میکنیم.
زمانی که همه عناصر فوق را تعریف کردیم، با استفاده از React State منطق آن را نیز اضافه میکنیم به طوری که به صورت پیشفرض Container Div پنهان باشد و زمانی که کاربر روی ورودی کلیک کرد، نمایان خواهد شد. زمانی که خارج از آن کلیک شود، انتظار طبیعی کاربر این است که DatePicker بسته شود، بنابراین این منطق را نیز اضافه میکنیم.
زمانی که کار تنظیم ابتدایی DatePicker به پایان رسید، آن را در App.js ایمپورت میکنیم. اینک کدبیس ما به صورت زیر در آمده است:
فایل MyDatePicker.js
1import React, {Component} from 'react';
2import ReactDOM from 'react-dom';
3import './MyDatePicker.css';
4
5let oneDay = 60 * 60 * 24 * 1000;
6let todayTimestamp = Date.now() - (Date.now() % oneDay) + (new Date().getTimezoneOffset() * 1000 * 60);
7
8export default class MyDatePicker extends Component {
9
10 state = {
11 getMonthDetails: []
12 }
13
14 componentDidMount() {
15 window.addEventListener('click', this.addBackDrop);
16 }
17
18 componentWillUnmount() {
19 window.removeEventListener('click', this.addBackDrop);
20 }
21
22 addBackDrop =e=> {
23 if(this.state.showDatePicker && !ReactDOM.findDOMNode(this).contains(e.target)) {
24 this.showDatePicker(false);
25 }
26 }
27
28 showDatePicker =(showDatePicker=true)=> {
29 this.setState({ showDatePicker })
30 }
31
32 render() {
33 return (
34 <div className='MyDatePicker'>
35 <div className='mdp-input' onClick={()=> this.showDatePicker(true)}>
36 <input type='date'/>
37 </div>
38 {this.state.showDatePicker ? (
39 <div className='mdp-container'>
40 </div>
41 ) : ''}
42 </div>
43 )
44 }
45
46}
فایل MyDatePicker.css
1.MyDatePicker {
2 float: left;
3 position: relative;
4}
5.MyDatePicker * {
6 -webkit-touch-callout: none; /* iOS Safari */
7 -webkit-user-select: none; /* Chrome/Safari/Opera */
8 -khtml-user-select: none; /* Konqueror */
9 -moz-user-select: none; /* Firefox */
10 -ms-user-select: none; /* Internet Explorer/Edge */
11 user-select: none; /* Non-prefixed version, currently */
12}
13
14.mdp-input{
15 float: left;
16 width: 150px;
17 height: 35px;
18 overflow: hidden;
19 border-radius: 20px;
20}
21.mdp-input input:focus{
22 outline: none;
23}
24.mdp-input input{
25 width: 125%;
26 background: #f5f5f5;
27 border: none;
28 height: 35px;
29 text-align: center;
30 text-transform: uppercase;
31 letter-spacing: 2px;
32 font-size: 11px;
33 cursor: pointer;
34}
35
36.mdp-container {
37 float: left;
38 position: absolute;
39 left:0;
40 top: 40px;
41 width: 300px;
42 min-height: 350px;
43 background: #fff;
44 box-shadow: 10px 10px 40px rgba(0,0,0,0.2);
45 border-radius: 20px;
46 overflow: hidden;
47 padding: 25px 30px;
48}
فایل App.js
1import React from 'react';
2import './App.css';
3import MyDatePicker from './MyDatePicker/MyDatePicker'
4
5function onChange(timestamp) {
6 console.log(timestamp);
7}
8
9function App() {
10 return (
11 <div className="App">
12 <MyDatePicker onChange={onChange}/>
13 </div>
14 );
15}
16
17export default App;
فایل App.css
1@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400,700&display=swap');
2
3.App {
4 float: left;
5 padding: 200px;
6}
7.App * {
8 font-family: 'Open Sans', sans-serif;
9}
بدین ترتیب باید چیزی مانند تصویر زیر را روی صفحه ببینید:
کد اصلی انتخابگر تاریخ
هسته اصلی انتخابگر تاریخ اقدام به پر کردن روزهای ماه میکند و به این منظور به 2 چیز نیاز داریم. یکی تعداد روزهای ماه و دیگری این که ماه از چه روزی آغاز میشود.
آغاز ماه
برای به دست آوردن روز آغاز ماه یک API داخلی در جاوا اسکریپت وجود دارد:
1new Date(year, month).getDay()
دستور فوق مقداری بین 0 تا 6 بازگشت میدهد که 0 نمایانگر روز یکشنبه و 6 نشاندهنده روز شنبه است.
تعداد روزها
برای به دست آوردن تعداد روزهای یک ماه، از API داخلی جاوا اسکریپت به همراه یک منطق ساده استفاده میکنیم:
1new Date(2019, 11, 12).getDate()
کد فوق روز جاری را که در اینجا 12 است بازگشت میدهد. اگر تلاش کنیم کدی به صورت زیر بنویسیم:
1new Date(2019, 11, 40)
عدد 9 به دست میآید، یعنی از روز 1 دسامبر 2019 40 روز گذشته است، یعنی 9 روز از ماه بعدی هم سپری شده است. بدین ترتیب 9 را از 40 کسر میکنیم و عدد 31 به دست میآید که برابر با تعداد روزهای ماه دسامبر 2019 است.
دقت کنید که در اینجا عدد 40 به عنوان یک مثال در نظر گرفته شده است، شما میتوانید هر مقداری که بزرگتر از 31 و کمتر از 60 باشد، انتخاب کنید. دلیل این که عدد 31 را انتخاب میکنیم آن است که روزهای طولانیترین ماه سال از این عدد بیشتر نیست و بدین ترتیب مقدار به دست آمده نباید از 59 بزرگتر باشد. اگر عدد به دست آمده از 59 بزرگتر باشد، این احتمال وجود دارد که ماه بعد را رد کنیم و تاریخی از ماه پس از آن به دست آوردیم.
اینک دو چیز داریم که برای پر کردن روزهای ماه لازم هستند. این بخش دشواری است که در زمان ساخت انتخابگر تاریخ با آن مواجه میشویم. از آنجا که منطق انتخابگر تاریخ را در اختیار داریم، میتوانیم ادیتور کد را باز کرده و آن را پیادهسازی کنیم.
پیادهسازی
با افزودن دو Div به Container Div آن را افراز میکنیم که یکی از آنها عنوان انتخابگر تاریخ است که سال و ماه را نمایش داده و دکمههایی برای حرکت در میان ماهها و سالها در اختیار ما قرار میدهد
Div دوم بدنه انتخابگر تاریخ است که شبکه تاریخها را رندر میکند. این شبکه در ابعاد 6 در 7 است که 7 تعداد ستونها و 6 تعداد ردیفها است. در ابتدای شبکه، یک ردیف دیگر اضافه میکنیم که نام روزها در آن پر میشوند.
بدین ترتیب دکمهها را به رویدادهای کلیک دکمههای تغییر سال و ماه متصل میکنیم. سپس باید روز جاری و روز انتخاب شده را نیز هایلایت کنیم.
پس از این پیادهسازی کد ما به صورت زیر درمیآید:
فایل MyDatePicker.js
1import React, {Component} from 'react';
2import ReactDOM from 'react-dom';
3import './MyDatePicker.css';
4
5let oneDay = 60 * 60 * 24 * 1000;
6let todayTimestamp = Date.now() - (Date.now() % oneDay) + (new Date().getTimezoneOffset() * 1000 * 60);
7let inputRef = React.createRef();
8
9export default class MyDatePicker extends Component {
10
11 state = {
12 getMonthDetails: []
13 }
14
15 constructor() {
16 super();
17 let date = new Date();
18 let year = date.getFullYear();
19 let month = date.getMonth();
20 this.state = {
21 year,
22 month,
23 selectedDay: todayTimestamp,
24 monthDetails: this.getMonthDetails(year, month)
25 }
26 }
27
28 componentDidMount() {
29 window.addEventListener('click', this.addBackDrop);
30 this.setDateToInput(this.state.selectedDay);
31 }
32
33 componentWillUnmount() {
34 window.removeEventListener('click', this.addBackDrop);
35 }
36
37 addBackDrop =e=> {
38 if(this.state.showDatePicker && !ReactDOM.findDOMNode(this).contains(e.target)) {
39 this.showDatePicker(false);
40 }
41 }
42
43 showDatePicker =(showDatePicker=true)=> {
44 this.setState({ showDatePicker })
45 }
46
47 /**
48 * Core
49 */
50
51 daysMap = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
52 monthMap = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
53
54 getDayDetails =args=> {
55 let date = args.index - args.firstDay;
56 let day = args.index%7;
57 let prevMonth = args.month-1;
58 let prevYear = args.year;
59 if(prevMonth < 0) {
60 prevMonth = 11;
61 prevYear--;
62 }
63 let prevMonthNumberOfDays = this.getNumberOfDays(prevYear, prevMonth);
64 let _date = (date < 0 ? prevMonthNumberOfDays+date : date % args.numberOfDays) + 1;
65 let month = date < 0 ? -1 : date >= args.numberOfDays ? 1 : 0;
66 let timestamp = new Date(args.year, args.month, _date).getTime();
67 return {
68 date: _date,
69 day,
70 month,
71 timestamp,
72 dayString: this.daysMap[day]
73 }
74 }
75
76 getNumberOfDays =(year, month)=> {
77 return 40 - new Date(year, month, 40).getDate();
78 }
79
80 getMonthDetails =(year, month)=> {
81 let firstDay = (new Date(year, month)).getDay();
82 let numberOfDays = this.getNumberOfDays(year, month);
83 let monthArray = [];
84 let rows = 6;
85 let currentDay = null;
86 let index = 0;
87 let cols = 7;
88
89 for(let row=0; row<rows; row++) {
90 for(let col=0; col<cols; col++) {
91 currentDay = this.getDayDetails({
92 index,
93 numberOfDays,
94 firstDay,
95 year,
96 month
97 });
98 monthArray.push(currentDay);
99 index++;
100 }
101 }
102 return monthArray;
103 }
104
105 isCurrentDay =day=> {
106 return day.timestamp === todayTimestamp;
107 }
108
109 isSelectedDay =day=> {
110 return day.timestamp === this.state.selectedDay;
111 }
112
113 getDateFromDateString =dateValue=> {
114 let dateData = dateValue.split('-').map(d=>parseInt(d, 10));
115 if(dateData.length < 3)
116 return null;
117
118 let year = dateData[0];
119 let month = dateData[1];
120 let date = dateData[2];
121 return {year, month, date};
122 }
123
124 getMonthStr =month=> this.monthMap[Math.max(Math.min(11, month), 0)] || 'Month';
125
126 getDateStringFromTimestamp =timestamp=> {
127 let dateObject = new Date(timestamp);
128 let month = dateObject.getMonth()+1;
129 let date = dateObject.getDate();
130 return dateObject.getFullYear() + '-' + (month < 10 ? '0'+month : month) + '-' + (date < 10 ? '0'+date : date);
131 }
132
133 setDate =dateData=> {
134 let selectedDay = new Date(dateData.year, dateData.month-1, dateData.date).getTime();
135 this.setState({ selectedDay })
136 if(this.props.onChange) {
137 this.props.onChange(selectedDay);
138 }
139 }
140
141 updateDateFromInput =()=> {
142 let dateValue = inputRef.current.value;
143 let dateData = this.getDateFromDateString(dateValue);
144 if(dateData !== null) {
145 this.setDate(dateData);
146 this.setState({
147 year: dateData.year,
148 month: dateData.month-1,
149 monthDetails: this.getMonthDetails(dateData.year, dateData.month-1)
150 })
151 }
152 }
153
154 setDateToInput =(timestamp)=> {
155 let dateString = this.getDateStringFromTimestamp(timestamp);
156 inputRef.current.value = dateString;
157 }
158
159 onDateClick =day=> {
160 this.setState({selectedDay: day.timestamp}, ()=>this.setDateToInput(day.timestamp));
161 if(this.props.onChange) {
162 this.props.onChange(day.timestamp);
163 }
164 }
165
166 setYear =offset=> {
167 let year = this.state.year + offset;
168 let month = this.state.month;
169 this.setState({
170 year,
171 monthDetails: this.getMonthDetails(year, month)
172 })
173 }
174
175 setMonth =offset=> {
176 let year = this.state.year;
177 let month = this.state.month + offset;
178 if(month === -1) {
179 month = 11;
180 year--;
181 } else if(month === 12) {
182 month = 0;
183 year++;
184 }
185 this.setState({
186 year,
187 month,
188 monthDetails: this.getMonthDetails(year, month)
189 })
190 }
191
192 /**
193 * Renderers
194 */
195
196 renderCalendar() {
197 let days = this.state.monthDetails.map((day, index)=> {
198 return (
199 <div className={'c-day-container ' + (day.month !== 0 ? ' disabled' : '') +
200 (this.isCurrentDay(day) ? ' highlight' : '') + (this.isSelectedDay(day) ? ' highlight-green' : '')} key={index}>
201 <div className='cdc-day'>
202 <span onClick={()=>this.onDateClick(day)}>
203 {day.date}
204 </span>
205 </div>
206 </div>
207 )
208 })
209
210 return (
211 <div className='c-container'>
212 <div className='cc-head'>
213 {['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'].map((d,i)=><div key={i} className='cch-name'>{d}</div>)}
214 </div>
215 <div className='cc-body'>
216 {days}
217 </div>
218 </div>
219 )
220 }
221
222 render() {
223 return (
224 <div className='MyDatePicker'>
225 <div className='mdp-input' onClick={()=> this.showDatePicker(true)}>
226 <input type='date' onChange={this.updateDateFromInput} ref={inputRef}/>
227 </div>
228 {this.state.showDatePicker ? (
229 <div className='mdp-container'>
230 <div className='mdpc-head'>
231 <div className='mdpch-button'>
232 <div className='mdpchb-inner' onClick={()=> this.setYear(-1)}>
233 <span className='mdpchbi-left-arrows'></span>
234 </div>
235 </div>
236 <div className='mdpch-button'>
237 <div className='mdpchb-inner' onClick={()=> this.setMonth(-1)}>
238 <span className='mdpchbi-left-arrow'></span>
239 </div>
240 </div>
241 <div className='mdpch-container'>
242 <div className='mdpchc-year'>{this.state.year}</div>
243 <div className='mdpchc-month'>{this.getMonthStr(this.state.month)}</div>
244 </div>
245 <div className='mdpch-button'>
246 <div className='mdpchb-inner' onClick={()=> this.setMonth(1)}>
247 <span className='mdpchbi-right-arrow'></span>
248 </div>
249 </div>
250 <div className='mdpch-button' onClick={()=> this.setYear(1)}>
251 <div className='mdpchb-inner'>
252 <span className='mdpchbi-right-arrows'></span>
253 </div>
254 </div>
255 </div>
256 <div className='mdpc-body'>
257 {this.renderCalendar()}
258 </div>
259 </div>
260 ) : ''}
261 </div>
262 )
263 }
264
265}
فایل MyDatePicker.css
1.MyDatePicker {
2 float: left;
3 position: relative;
4}
5.MyDatePicker * {
6 -webkit-touch-callout: none; /* iOS Safari */
7 -webkit-user-select: none; /* Chrome/Safari/Opera */
8 -khtml-user-select: none; /* Konqueror */
9 -moz-user-select: none; /* Firefox */
10 -ms-user-select: none; /* Internet Explorer/Edge */
11 user-select: none; /* Non-prefixed version, currently */
12}
13
14.mdp-input{
15 float: left;
16 width: 150px;
17 height: 35px;
18 overflow: hidden;
19 border-radius: 20px;
20}
21.mdp-input input:focus{
22 outline: none;
23}
24.mdp-input input{
25 width: 130%;
26 background: #f5f5f5;
27 border: none;
28 padding-right: 10px;
29 height: 35px;
30 text-align: center;
31 text-transform: uppercase;
32 letter-spacing: 2px;
33 font-size: 11px;
34 cursor: pointer;
35}
36
37.mdp-container {
38 float: left;
39 position: absolute;
40 left:0;
41 top: 40px;
42 width: 300px;
43 min-height: 350px;
44 background: #fff;
45 box-shadow: 10px 10px 40px rgba(0,0,0,0.2);
46 border-radius: 20px;
47 overflow: hidden;
48 padding: 25px 30px;
49}
50.mdpc-head{
51 float: left;
52 width: 100%;
53 height: 53px;
54}
55.mdpc-body{
56 float: left;
57 width: 100%;
58 margin-top: 20px;
59}
60
61/**
62 * Controls
63 */
64
65.mdpch-button{
66 float: left;
67 width: 45px;
68 height: 100%;
69 box-sizing: border-box;
70 position: relative;
71}
72.mdpchb-inner:hover > span{
73 border-color: #555!important;
74}
75.mdpchb-inner:hover{
76 cursor: pointer;
77 background: #eee;
78}
79.mdpchb-inner {
80 float: left;
81 height: 35px;
82 width: 35px;
83 background: #f4f4f4;
84 border-radius: 100%;
85 line-height: 35px;
86 text-align: center;
87 position: absolute;
88 top:50%;
89 left: 50%;
90 margin-left: -17px;
91 margin-top: -17px;
92}
93
94.mdpchbi-right-arrows:after,
95.mdpchbi-left-arrows:after,
96.mdpchbi-right-arrow,
97.mdpchbi-right-arrows,
98.mdpchbi-left-arrow,
99.mdpchbi-left-arrows{
100 display: block;
101 float: left;
102 width: 6px;
103 height: 6px;
104 border-left: 2px solid #888;
105 border-bottom: 2px solid #888;
106 position: absolute;
107}
108.mdpchbi-right-arrow,
109.mdpchbi-right-arrows,
110.mdpchbi-left-arrow,
111.mdpchbi-left-arrows{
112 transform: rotate(45deg);
113 left: 50%;
114 top:50%;
115 margin-left: -2px;
116 margin-top: -4px;
117}
118.mdpchbi-right-arrows,
119.mdpchbi-right-arrow {
120 transform: rotate(225deg);
121 margin-left: -4px;
122}
123.mdpchbi-right-arrows:after,
124.mdpchbi-left-arrows:after{
125 content: '';
126}
127
128.mdpchbi-left-arrows{
129 margin-left: -5px;
130}
131.mdpchbi-right-arrows{
132 margin-left: -2px;
133}
134.mdpchbi-right-arrows:after,
135.mdpchbi-left-arrows:after{
136 left: 3px;
137 top: -5px
138}
139
140
141.mdpch-container{
142 float: left;
143 width: 120px;
144 height: 100%;
145}
146.mdpchc-year{
147 float: left;
148 width: 100%;
149 height: 30px;
150 font-size: 27px;
151 color: #666;
152 font-weight: 200px;
153 text-align: center;
154}
155.mdpchc-month{
156 float: left;
157 width: 100%;
158 height: 15px;
159 font-size: 13px;
160 color: #666;
161 font-weight: 200px;
162 text-align: center;
163}
164
165/**
166 * Calendar
167 */
168.cc-month,
169.cc-head,
170.cch-name,
171.cc-body,
172.cdc-day span,
173.cdc-day,
174.c-day-container,
175.c-container{
176 position: relative;
177 display: block;
178 float: left;
179 -webkit-box-sizing: border-box;
180 -moz-box-sizing: border-box;
181 box-sizing: border-box;
182}
183
184.c-container{
185 width: 100%;
186 height: 100%;
187}
188
189.cc-month{
190 height: 30px;
191 width: 100%;
192 font-family: Roboto;
193 font-size: 16px;
194 line-height: 30px;
195 color: #666;
196}
197.cc-head{
198 height: 30px;
199 width: 100%;
200 margin-top: 10px;
201}
202.cch-name{
203 width: 14.285%;
204 height: 30px;
205 line-height: 30px;
206 font-weight: 700;
207 color: #666;
208 font-size: 9px;
209 text-align: center;
210}
211.cc-body{
212 height: 270px;
213 width: 100%;
214}
215.c-day-container{
216 width: 14.285%;
217 height: 16.6666%;
218}
219.cdc-day{
220 width: 100%;
221 height: 100%;
222 font-size: 12px;
223 font-weight: 300;
224 color: #444;
225 text-align: center;
226}
227.cdc-day span{
228 width: 100%;
229 height: 100%;
230 font-size: 12px;
231 font-weight: 300;
232 color: #444;
233}
234
235.cdc-day span:hover{
236 cursor: pointer;
237 background: #eee;
238}
239.cdc-day span{
240 width: 30px;
241 height: 30px;
242 margin-top: -15px;
243 margin-left: -15px;
244 left: 50%;
245 top: 50%;
246 font-weight: 400;
247 border-radius: 100%;
248 line-height: 30px;
249}
250.c-day-container.disabled{
251 pointer-events: none;
252}
253
254.c-day-container.disabled .cdc-day span{
255 color: #ddd;
256}
257.c-day-container.disabled .cdc-day span{
258 background: #fff!important;
259}
260.c-day-container.highlight .cdc-day span{
261 background: #efdbca;
262}
263.c-day-container.highlight-green .cdc-day span{
264 background: #d4e2cb;
265}
پس از بهروزرسانی کدبیس به صورت فوق، یک انتخابگر تاریخ عملیاتی در مرورگر به دست میآید. برای مشاهده یک دموی عملی از این انتخابگر تاریخ میتوانید به این صفحه (+) مراجعه کنید. از طرف دیگر اگر نمیخواهید درگیر فرایند توسعه این کتابخانه بشوید، میتوانید آن را از این آدرس (+) مورد استفاده کنید.
سخن پایانی
اغلب چیزهایی که به ظاهر دشوار میرسند، در عمل بسیار آسان هستند، کافی است دست به کار شوید و آن را اجرا کنید. در این مقاله با شیوه ساخت یک انتخابگر تاریخ از صفر تا صد و بدون استفاده از هیچ کتابخانه دیگر آشنا شدیم. اینک میتوانید API-های خود را به این DatePicker اضافه کنید و همچنین قالببندی و امکانات متنوعی به آن بیفزایید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- ۱۰ نکته و ترفند برای بهبود برنامه نویسی React — راهنمای کاربردی
- ۴ قلاب سفارشی React برای ارتقای عملکرد اپلیکیشن ها — راهنمای کاربردی
- ایجاد نوار پیشروی در React — از صفر تا صد
==