ساخت انتخابگر تاریخ در جاوا اسکریپت — از صفر تا صد

۲۸۹ بازدید
آخرین به‌روزرسانی: ۰۷ شهریور ۱۴۰۲
زمان مطالعه: ۱۰ دقیقه
ساخت انتخابگر تاریخ در جاوا اسکریپت — از صفر تا صد

اغلب ما فکر می‌کنیم که ساخت یک انتخابگر تاریخ کار سختی است. در این مقاله نشان می‌دهیم که ساخت انتخابگر تاریخ در جاوا اسکریپت و ری‌اکت کار بسیار ساده‌ای است. این کار را به کمک شیء داده جاوا اسکریپت انجام می‌دهیم. ما از 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 اضافه کنید و همچنین قالب‌بندی و امکانات متنوعی به آن بیفزایید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۱ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
swlh
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *