Custom Date and Time Picker Using HTML, CSS, and JavaScript

By Bytewebster - August 14, 2023




Welcome to ByteWebster Front-End Projects, In this project, we are creating a custom date and time picker using HTML, CSS, and Javascript. And in this project, we will explain to you how it is made.

Working:

In this project, A calendar has been given to select the date; as soon as the date is selected from that calendar, it will appear in the upper header. There is also a time picker that allows you to select a time, including hours and minutes. While selecting the time, two options, AM and PM, are also present. And as soon as the AM option is selected, the theme of this date and time picker changes to a light colour, and when the PM option is selected, the theme changes to orange.

                     
                 
Detailed Overview of Project

This date-time picker can be used in many web development projects where you need to input specific date and time information, for example, in Task and Project management, forms, etc.

We have made this project in such a way that if you have to implement it anywhere, you will not face any problems. Its entire interface is user-friendly. Let's start by breaking down the HTML part of it.


HTML Structure


This entire date-time picker is enclosed in a container that has a specific style. This container holds the date-time picker component. Inside this container, There's a section with a title, a header, a calendar section, and on the right side, a time picker.

Next, The header of this date-time picker shows the title and a custom message along with the selected date and time. Also, There's a calendar section where you can navigate through months and select a specific day. It is very important to note that The days of the week are displayed as labels in the calendar.

Next, there is another container, which is am-pm-container." By using this, You can switch between AM and PM using buttons provided in the "am-pm-container" section.


<div class="app-container" ng-app="dateTimeApp" ng-controller="dateTimeCtrl as ctrl" ng-cloak>
    <div date-picker datepicker-title="Select Date" picktime="true" pickdate="true" pickpast="false" mondayfirst="false" custom-message="You have selected" selecteddate="ctrl.selected_date" updatefn="ctrl.updateDate(newdate)">
        <div
            class="datepicker"
            ng-class="{
				'am': timeframe == 'am',
				'pm': timeframe == 'pm',
				'compact': compact
			}"
        >
            <div class="datepicker-header">
                <div class="datepicker-title" ng-if="datepicker_title">{{ datepickerTitle }}</div>
                <div class="datepicker-subheader">{{ customMessage }} {{ selectedDay }} {{ monthNames[localdate.getMonth()] }} {{ localdate.getDate() }}, {{ localdate.getFullYear() }}</div>
            </div>
            <div class="datepicker-calendar">
                <div class="calendar-header">
                    <div class="goback" ng-click="moveBack()" ng-if="pickdate">
                        <svg width="30" height="30">
                            <path fill="none" stroke="#0DAD83" stroke-width="3" d="M19,6 l-9,9 l9,9" />
                        </svg>
                    </div>
                    <div class="current-month-container">{{ currentViewDate.getFullYear() }} {{ currentMonthName() }}</div>
                    <div class="goforward" ng-click="moveForward()" ng-if="pickdate">
                        <svg width="30" height="30">
                            <path fill="none" stroke="#0DAD83" stroke-width="3" d="M11,6 l9,9 l-9,9" />
                        </svg>
                    </div>
                </div>
                <div class="calendar-day-header">
                    <span ng-repeat="day in days" class="day-label">{{ day.short }}</span>
                </div>
                <div class="calendar-grid" ng-class="{false: 'no-hover'}[pickdate]">
                    <div ng-class="{'no-hover': !day.showday}" ng-repeat="day in month" class="datecontainer" ng-style="{'margin-left': calcOffset(day, $index)}" track by $index>
                        <div class="datenumber" ng-class="{'day-selected': day.selected }" ng-click="selectDate(day)">
                            {{ day.daydate }}
                        </div>
                    </div>
                </div>
            </div>
            <div class="timepicker" ng-if="picktime == 'true'">
                <div ng-class="{'am': timeframe == 'am', 'pm': timeframe == 'pm' }">
                    <div class="timepicker-container-outer" selectedtime="time" timetravel>
                        <div class="timepicker-container-inner">
                            <div class="timeline-container" ng-mousedown="timeSelectStart($event)" sm-touchstart="timeSelectStart($event)">
                                <div class="current-time">
                                    <div class="actual-time">{{ time }}</div>
                                </div>
                                <div class="timeline"></div>
                                <div class="hours-container">
                                    <div class="hour-mark" ng-repeat="hour in getHours() track by $index"></div>
                                </div>
                            </div>
                            <div class="display-time">
                                <div class="decrement-time" ng-click="adjustTime('decrease')">
                                    <svg width="24" height="24">
                                        <path stroke="white" stroke-width="2" d="M8,12 h8" />
                                    </svg>
                                </div>
                                <div class="time" ng-class="{'time-active': edittime.active}">
                                    <input type="text" class="time-input" ng-model="edittime.input" ng-keydown="changeInputTime($event)" ng-focus="edittime.active = true; edittime.digits = [];" ng-blur="edittime.active = false" />
                                    <div class="formatted-time">{{ edittime.formatted }}</div>
                                </div>
                                <div class="increment-time" ng-click="adjustTime('increase')">
                                    <svg width="24" height="24">
                                        <path stroke="white" stroke-width="2" d="M12,7 v10 M7,12 h10" />
                                    </svg>
                                </div>
                            </div>
                            <div class="am-pm-container">
                                <div class="am-pm-button" ng-click="changetime('am');">am</div>
                                <div class="am-pm-button" ng-click="changetime('pm');">pm</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="buttons-container">
                <div class="cancel-button">CANCEL</div>
                <div class="save-button">SAVE</div>
            </div>
        </div>
    </div>
</div>

Also, there are two major directives in this HTML code. The first one is the "ng-repeat" directive, which is used to generate day labels and date containers. and the second one is the "ng-click" directive, which is used to trigger functions when the user clicks on the previous or next month options.

Finally, at the bottom of this custom date-time picker, there are "CANCEL" and "SAVE" buttons. These buttons perform actions such as cancelling the date-time selection or saving the chosen date and time.


Styling With CSS


We Hope you have understood its structure, and now we are moving on to the next step so that this date and time picker can be designed. So let's start with Styling the Date Picker container.

In this container, the datepicker class styles the main container for the datepicker interface. Then come the background colours for AM and PM buttons. The datepicker.am and datepicker.pm classes change the background color based on whether the picker is in AM or PM mode.

Note: Before proceeding, let us tell you that the CSS code given below is not complete. To get the complete code, you have to download it by clicking on the button given below.


.buttons-container {
    position: absolute;
    bottom: 15px;
    right: 0;
    height: 40px;
    font-family: "Roboto", sans-serif;
}

.cancel-button,
.save-button {
    float: left;
    height: 40px;
    line-height: 40px;
    padding: 0 15px;
    border-radius: 2px;
    margin-right: 15px;
    cursor: pointer;
    transition: all 0.15s ease;
}

.cancel-button {
    background: white;
    color: #ff5b38;
}

.save-button {
    background: #ff5b38;
    color: white;
}

.datepicker {
    position: relative;
    width: 100%;
    display: block;
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
    font-family: "Roboto", sans-serif;
    overflow: hidden;
    transition: background 0.15s ease;
}

.datepicker.am {
    background: white;
}

.datepicker.pm {
    background: #ff5b38;
}

.datepicker-header {
    width: 100%;
    color: white;
    overflow: hidden;
}

.datepicker-title {
    width: 50%;
    float: left;
    height: 60px;
    line-height: 60px;
    padding: 0 15px;
    text-align: left;
    font-size: 20px;
}

.datepicker-subheader {
    width: 50%;
    float: left;
    height: 60px;
    line-height: 60px;
    font-size: 14px;
    padding: 0 15px;
    text-align: right;
}

.datepicker-calendar {
    width: 50%;
    float: left;
    padding: 20px 15px 15px;
    max-width: 400px;
    display: block;
}

.calendar-header {
    color: black;
    font-weight: bolder;
    text-align: center;
    font-size: 18px;
    padding: 10px 0;
    position: relative;
}

.current-month-container {
    display: inline-block;
    height: 30px;
    position: relative;
}

.goback,
.goforward {
    height: 30px;
    width: 30px;
    border-radius: 30px;
    display: inline-block;
    cursor: pointer;
    position: relative;
    top: -4px;
}

.goback path,
.goforward path {
    transition: stroke 0.15s ease;
}

.goback {
    float: left;
    margin-left: 3.8%;
}

.goforward {
    float: right;
    margin-right: 3.8%;
}

.calendar-day-header {
    width: 100%;
    position: relative;
}

.day-label {
    color: #8a8a8a;
    padding: 5px 0;
    width: 14.2857142%;
    display: inline-block;
    text-align: center;
}

.datecontainer {
    width: 14.2857142%;
    display: inline-block;
    text-align: center;
    padding: 4px 0;
}

.datenumber {
    max-width: 35px;
    max-height: 35px;
    line-height: 35px;
    margin: 0 auto;
    color: #8a8a8a;
    position: relative;
    text-align: center;
    cursor: pointer;
    z-index: 1;
    transition: all 0.25s cubic-bezier(0.7, -0.12, 0.2, 1.12);
}

.no-hover .datenumber,
.no-hover .datenumber:hover,
.no-hover .datenumber:before,
.no-hover .datenumber:hover::before {
    cursor: default;
    color: #8a8a8a;
    background: transparent;
    opacity: 0.5;
}

.no-hover .datenumber.day-selected {
    color: white;
}

.datenumber:hover {
    color: white;
}

.datenumber:before {
    content: "";
    display: block;
    position: absolute;
    height: 35px;
    width: 35px;
    border-radius: 100px;
    z-index: -1;
    background: transparent;
    transform: scale(0.75);
    transition: all 0.25s cubic-bezier(0.7, -0.12, 0.2, 1.12);
    transition-property: background, transform, color, border;
}

.datenumber:hover::before {
    background: #ffab91;
    transform: scale(1);
}

.day-selected {
    color: white;
}

.datenumber.day-selected:before {
    background: #ff6e40;
    transform: scale(1);
    -webkit-animation: select-date 0.25s forwards;
    animation: select-date 0.25s forwards;
}

@-webkit-keyframes select-date {
    0% {
        background: #ffab91;
    }
    100% {
        background: #ff6e40;
    }
}
@keyframes select-date {
    0% {
        background: #ffab91;
    }
    100% {
        background: #ff6e40;
    }
}
/* timepicker styles */
.timepicker-container-outer {
    width: 50%;
    max-width: 700px;
    float: left;
    display: block;
    padding: 40px 30px 30px;
    position: relative;
    top: 50px;
    overflow: hidden;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s ease;
}

.timepicker-container-inner {
    width: 100%;
    height: 100%;
    max-width: 320px;
    margin: 0 auto;
    position: relative;
    display: block;
}

.timeline-container {
    display: block;
    float: left;
    position: relative;
    width: 100%;
    height: 36px;
}

.current-time {
    display: block;
    position: absolute;
    z-index: 1;
    width: 40px;
    height: 40px;
    border-radius: 20px;
    top: -25px;
    left: -20px;
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

.current-time::after {
    content: "";
    display: block;
    width: 40px;
    height: 40px;
    position: absolute;
    background: #ff6e40;
    transition: all 0.15s ease;
    transform: rotate(45deg);
    border-radius: 20px 20px 3px 20px;
    z-index: -1;
    top: 0;
}

.actual-time {
    color: white;
    line-height: 40px;
    font-size: 12px;
    text-align: center;
    transition: all 0.15s ease;
}

.timeline {
    display: block;
    z-index: 1;
    width: 100%;
    height: 2px;
    position: absolute;
    bottom: 0;
}

.timeline::after {
    left: auto;
    right: -1px;
}

.hours-container {
    display: block;
    z-index: 0;
    width: 100%;
    height: 10px;
    position: absolute;
    top: 31px;
    left: 1px;
}

.hour-mark {
    width: 2px;
    display: block;
    float: left;
    height: 4px;
    background: #ff5b38;
    position: relative;
    margin-left: calc((100% / 12) - 2px);
    transition: background 0.15s ease;
}

.hour-mark:nth-child(3n) {
    height: 6px;
    top: -1px;
}

.decrement-time {
    left: 0;
    text-align: left;
}

.increment-time {
    right: 0;
    text-align: right;
}

.increment-time path,
.decrement-time path {
    transition: all 0.15s ease;
}

.time {
    width: calc(100% - 48px);
    position: relative;
    left: 24px;
    height: 36px;
}

.am-pm-button {
    width: calc(50% - 5px);
    height: 36px;
    line-height: 36px;
    background: #2196f3;
    text-align: center;
    color: white;
    border-radius: 4px;
    float: left;
    cursor: pointer;
}

.am-pm-button:first-child {
    background: #ff5b38;
    color: white;
}

.am-pm-button:last-child {
    background: white;
    color: #ff5b38;
    margin-left: 10px;
}

The Header section of this date and time picker style is provided by the datepicker-header class. This class styles the header section containing the title and subheader.

For styling the calendar of this date-time picker, we created a datepicker-calendar class that Styles the section containing the date grid and also the header of the calendar with month and navigation controls.

Finally, we style the Time Picker by using the timepicker-container-outer class. This class styles the outer container of the time picker. and the second class, which is timepicker-container-inner, styles the inner container of the time picker.


JavaScript Explanation


Now let's move to the last and most important part, which is JavaScript, so that we can make this date and time picker functional. The JavaScript code for this custom date and time picker is written using the AngularJS framework.

First, we created an AngularJS module called dateTimeApp. Inside this module, we created a controller named dateTimeCtrl. This controller handles various tasks related to the date and time picker.

Next, we created a custom AngularJS directive that helps you create the date and time picker interface by using the specified attributes. Not only this, it also manages the options like selected date, update function, display format, time picker, date picker, etc.


var app = angular.module("dateTimeApp", []);
app.controller("dateTimeCtrl", function ($scope) {
    var ctrl = this;
    ctrl.selected_date = new Date();
    ctrl.selected_date.setHours(10);
    ctrl.selected_date.setMinutes(0);
    ctrl.updateDate = function (newdate) {
        console.log(newdate);
    };
});

app.directive("datePicker", function ($timeout, $window) {
    return {
        restrict: "AE",
        scope: {
            selecteddate: "=",
            updatefn: "&",
            open: "=",
            datepickerTitle: "@",
            customMessage: "@",
            picktime: "@",
            pickdate: "@",
            pickpast: "=",
            mondayfirst: "@",
        },
        transclude: true,
        link: function (scope, element, attrs, ctrl, transclude) {
            transclude(scope, function (clone, scope) {
                element.append(clone);
            });

            if (!scope.selecteddate) {
                scope.selecteddate = new Date();
            }

            if (attrs.datepickerTitle) {
                scope.datepicker_title = attrs.datepickerTitle;
            }

            scope.days = [
                { long: "Sunday", short: "Sun" },
                { long: "Monday", short: "Mon" },
                { long: "Tuesday", short: "Tue" },
                { long: "Wednesday", short: "Wed" },
                { long: "Thursday", short: "Thu" },
                { long: "Friday", short: "Fri" },
                { long: "Saturday", short: "Sat" },
            ];
            if (scope.mondayfirst == "true") {
                var sunday = scope.days[0];
                scope.days.shift();
                scope.days.push(sunday);
            }

            scope.monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

            function getSelected() {
                if (scope.currentViewDate.getMonth() == scope.localdate.getMonth()) {
                    if (scope.currentViewDate.getFullYear() == scope.localdate.getFullYear()) {
                        for (var number in scope.month) {
                            if (scope.month[number].daydate == scope.localdate.getDate()) {
                                scope.month[number].selected = true;
                                if (scope.mondayfirst == "true") {
                                    if (parseInt(number) === 0) {
                                        number = 6;
                                    } else {
                                        number = number - 1;
                                    }
                                }
                                scope.selectedDay = scope.days[scope.month[number].dayname].long;
                            }
                        }
                    }
                }
            }

            function getDaysInMonth() {
                var month = scope.currentViewDate.getMonth();
                var date = new Date(scope.currentViewDate.getFullYear(), month, 1);
                var days = [];
                var today = new Date();
                while (date.getMonth() === month) {
                    var showday = true;
                    if (!scope.pickpast && date < today) {
                        showday = false;
                    }
                    if (today.getDate() == date.getDate() && today.getYear() == date.getYear() && today.getMonth() == date.getMonth()) {
                        showday = true;
                    }
                    var day = new Date(date);
                    var dayname = day.getDay();
                    var daydate = day.getDate();
                    days.push({ dayname: dayname, daydate: daydate, showday: showday });
                    date.setDate(date.getDate() + 1);
                }
                scope.month = days;
            }

            function initializeDate() {
                scope.currentViewDate = new Date(scope.localdate);
                scope.currentMonthName = function () {
                    return scope.monthNames[scope.currentViewDate.getMonth()];
                };
                getDaysInMonth();
                getSelected();
            }

            function getDateAndTime(localdate) {
                var time = scope.time.split(":");
                if (scope.timeframe == "am" && time[0] == "12") {
                    time[0] = 0;
                } else if (scope.timeframe == "pm" && time[0] !== "12") {
                    time[0] = parseInt(time[0]) + 12;
                }
                return new Date(localdate.getFullYear(), localdate.getMonth(), localdate.getDate(), time[0], time[1]);
            }

            function convertToUTC(localdate) {
                var date_obj = getDateAndTime(localdate);
                var utcdate = new Date(date_obj.getUTCFullYear(), date_obj.getUTCMonth(), date_obj.getUTCDate(), date_obj.getUTCHours(), date_obj.getUTCMinutes());
                return utcdate;
            }

            function convertFromUTC(utcdate) {
                localdate = new Date(utcdate);
                return localdate;
            }

            function formatAMPM(date) {
                var hours = date.getHours();
                var minutes = date.getMinutes();
                hours >= 12 ? scope.changetime("pm") : scope.changetime("am");
                hours = hours % 12;
                hours = hours ? hours : 12;
                minutes = minutes < 10 ? "0" + minutes : minutes;
                var strTime = hours + ":" + minutes;
                return strTime;
            }

            scope.$watch("open", function () {
                if (scope.selecteddate !== undefined && scope.selecteddate !== null) {
                    scope.localdate = convertFromUTC(scope.selecteddate);
                } else {
                    scope.localdate = new Date();
                    scope.localdate.setMinutes(Math.round(scope.localdate.getMinutes() / 60) * 30);
                }
                scope.time = formatAMPM(scope.localdate);
                scope.setTimeBar(scope.localdate);
                initializeDate();
                scope.updateInputTime();
            });

            scope.selectDate = function (day) {
                if (scope.pickdate == "true" && day.showday) {
                    for (var number in scope.month) {
                        var item = scope.month[number];
                        if (item.selected === true) {
                            item.selected = false;
                        }
                    }
                    day.selected = true;
                    scope.selectedDay = scope.days[day.dayname].long;
                    scope.localdate = new Date(scope.currentViewDate.getFullYear(), scope.currentViewDate.getMonth(), day.daydate);
                    initializeDate(scope.localdate);
                    scope.updateDate();
                }
            };

            scope.updateDate = function () {
                if (scope.localdate) {
                    var newdate = getDateAndTime(scope.localdate);
                    scope.updatefn({ newdate: newdate });
                }
            };

            scope.moveForward = function () {
                scope.currentViewDate.setMonth(scope.currentViewDate.getMonth() + 1);
                if (scope.currentViewDate.getMonth() == 12) {
                    scope.currentViewDate.setDate(scope.currentViewDate.getFullYear() + 1, 0, 1);
                }
                getDaysInMonth();
                getSelected();
            };

            scope.moveBack = function () {
                scope.currentViewDate.setMonth(scope.currentViewDate.getMonth() - 1);
                if (scope.currentViewDate.getMonth() == -1) {
                    scope.currentViewDate.setDate(scope.currentViewDate.getFullYear() - 1, 0, 1);
                }
                getDaysInMonth();
                getSelected();
            };

            scope.calcOffset = function (day, index) {
                if (index === 0) {
                    var offset = day.dayname * 14.2857142 + "%";
                    if (scope.mondayfirst == "true") {
                        offset = (day.dayname - 1) * 14.2857142 + "%";
                    }
                    return offset;
                }
            };

            scope.checkWidth = function (apply) {
                var parent_width = element.parent().width();
                if (parent_width < 620) {
                    scope.compact = true;
                } else {
                    scope.compact = false;
                }
                if (apply) {
                    scope.$apply();
                }
            };
            scope.checkWidth(false);

            if (scope.picktime) {
                var currenttime;
                var timeline;
                var timeline_width;
                var timeline_container;
                var sectionlength;

                scope.getHours = function () {
                    var hours = new Array(11);
                    return hours;
                };

                scope.time = "12:00";
                scope.hour = 12;
                scope.minutes = 0;
                scope.currentoffset = 0;
                scope.timeframe = "am";

                scope.changetime = function (time) {
                    scope.timeframe = time;
                    scope.updateDate();
                    scope.updateInputTime();
                };

                scope.edittime = {
                    digits: [],
                };

                scope.updateInputTime = function () {
                    scope.edittime.input = scope.time + " " + scope.timeframe;
                    scope.edittime.formatted = scope.edittime.input;
                };

                scope.updateInputTime();

                function checkValidTime(number) {
                    validity = true;
                    switch (scope.edittime.digits.length) {
                        case 0:
                            if (number === 0) {
                                validity = false;
                            }
                            break;
                        case 1:
                            if (number > 5) {
                                validity = false;
                            } else {
                                validity = true;
                            }
                            break;
                        case 2:
                            validity = true;
                            break;
                        case 3:
                            if (scope.edittime.digits[0] > 1) {
                                validity = false;
                            } else if (scope.edittime.digits[1] > 2) {
                                validity = false;
                            } else if (scope.edittime.digits[2] > 5) {
                                validity = false;
                            } else {
                                validity = true;
                            }
                            break;
                        case 4:
                            validity = false;
                            break;
                    }
                    return validity;
                }

                function formatTime() {
                    var time = "";
                    if (scope.edittime.digits.length == 1) {
                        time = "--:-" + scope.edittime.digits[0];
                    } else if (scope.edittime.digits.length == 2) {
                        time = "--:" + scope.edittime.digits[0] + scope.edittime.digits[1];
                    } else if (scope.edittime.digits.length == 3) {
                        time = "-" + scope.edittime.digits[0] + ":" + scope.edittime.digits[1] + scope.edittime.digits[2];
                    } else if (scope.edittime.digits.length == 4) {
                        time = scope.edittime.digits[0] + scope.edittime.digits[1].toString() + ":" + scope.edittime.digits[2] + scope.edittime.digits[3];
                        console.log(time);
                    }
                    return time + " " + scope.timeframe;
                }

                scope.changeInputTime = function (event) {
                    var numbers = { 48: 0, 49: 1, 50: 2, 51: 3, 52: 4, 53: 5, 54: 6, 55: 7, 56: 8, 57: 9 };
                    if (numbers[event.which] !== undefined) {
                        if (checkValidTime(numbers[event.which])) {
                            scope.edittime.digits.push(numbers[event.which]);
                            console.log(scope.edittime.digits);
                            scope.time_input = formatTime();
                            scope.time = numbers[event.which] + ":00";
                            scope.updateDate();
                            scope.setTimeBar();
                        }
                    } else if (event.which == 65) {
                        scope.timeframe = "am";
                        scope.time_input = scope.time + " " + scope.timeframe;
                    } else if (event.which == 80) {
                        scope.timeframe = "pm";
                        scope.time_input = scope.time + " " + scope.timeframe;
                    } else if (event.which == 8) {
                        scope.edittime.digits.pop();
                        scope.time_input = formatTime();
                        console.log(scope.edittime.digits);
                    }
                    scope.edittime.formatted = scope.time_input;
                };

                var pad2 = function (number) {
                    return (number < 10 ? "0" : "") + number;
                };

                scope.moving = false;
                scope.offsetx = 0;
                scope.totaloffset = 0;
                scope.initializeTimepicker = function () {
                    currenttime = $(".current-time");
                    timeline = $(".timeline");
                    if (timeline.length > 0) {
                        timeline_width = timeline[0].offsetWidth;
                    }
                    timeline_container = $(".timeline-container");
                    sectionlength = timeline_width / 24 / 6;
                };

                angular.element($window).on("resize", function () {
                    scope.initializeTimepicker();
                    if (timeline.length > 0) {
                        timeline_width = timeline[0].offsetWidth;
                    }
                    sectionlength = timeline_width / 24;
                    scope.checkWidth(true);
                });

                scope.setTimeBar = function (date) {
                    currenttime = $(".current-time");
                    var timeline_width = $(".timeline")[0].offsetWidth;
                    var hours = scope.time.split(":")[0];
                    if (hours == 12) {
                        hours = 0;
                    }
                    var minutes = scope.time.split(":")[1];
                    var minutes_offset = (minutes / 60) * (timeline_width / 12);
                    var hours_offset = (hours / 12) * timeline_width;
                    scope.currentoffset = parseInt(hours_offset + minutes_offset - 1);
                    currenttime.css({
                        transition: "transform 0.4s ease",
                        transform: "translateX(" + scope.currentoffset + "px)",
                    });
                };

                scope.getTime = function () {
                    var percenttime = (scope.currentoffset + 1) / timeline_width;
                    var hour = Math.floor(percenttime * 12);
                    var percentminutes = percenttime * 12 - hour;
                    var minutes = Math.round((percentminutes * 60) / 5) * 5;
                    if (hour === 0) {
                        hour = 12;
                    }
                    if (minutes == 60) {
                        hour += 1;
                        minutes = 0;
                    }

                    scope.time = hour + ":" + pad2(minutes);
                    scope.updateInputTime();
                    scope.updateDate();
                };

                var initialized = false;

                element.on("touchstart", function () {
                    if (!initialized) {
                        element.find(".timeline-container").on("touchstart", function (event) {
                            scope.timeSelectStart(event);
                        });
                        initialized = true;
                    }
                });

                scope.timeSelectStart = function (event) {
                    scope.initializeTimepicker();
                    var timepicker_container = element.find(".timepicker-container-inner");
                    var timepicker_offset = timepicker_container.offset().left;
                    if (event.type == "mousedown") {
                        scope.xinitial = event.clientX;
                    } else if (event.type == "touchstart") {
                        scope.xinitial = event.originalEvent.touches[0].clientX;
                    }
                    scope.moving = true;
                    scope.currentoffset = scope.xinitial - timepicker_container.offset().left;
                    scope.totaloffset = scope.xinitial - timepicker_container.offset().left;
                    console.log(timepicker_container.width());
                    if (scope.currentoffset < 0) {
                        scope.currentoffset = 0;
                    } else if (scope.currentoffset > timepicker_container.width()) {
                        scope.currentoffset = timepicker_container.width();
                    }
                    currenttime.css({
                        transform: "translateX(" + scope.currentoffset + "px)",
                        transition: "none",
                        cursor: "ew-resize",
                    });
                    scope.getTime();
                };

                angular.element($window).on("mousemove touchmove", function (event) {
                    if (scope.moving === true) {
                        event.preventDefault();
                        if (event.type == "mousemove") {
                            scope.offsetx = event.clientX - scope.xinitial;
                        } else if (event.type == "touchmove") {
                            scope.offsetx = event.originalEvent.touches[0].clientX - scope.xinitial;
                        }
                        var movex = scope.offsetx + scope.totaloffset;
                        if (movex >= 0 && movex <= timeline_width) {
                            currenttime.css({
                                transform: "translateX(" + movex + "px)",
                            });
                            scope.currentoffset = movex;
                        } else if (movex < 0) {
                            currenttime.css({
                                transform: "translateX(0)",
                            });
                            scope.currentoffset = 0;
                        } else {
                            currenttime.css({
                                transform: "translateX(" + timeline_width + "px)",
                            });
                            scope.currentoffset = timeline_width;
                        }
                        scope.getTime();
                        scope.$apply();
                    }
                });

                angular.element($window).on("mouseup touchend", function (event) {
                    if (scope.moving) {
                    }
                    scope.moving = false;
                });

                scope.adjustTime = function (direction) {
                    event.preventDefault();
                    scope.initializeTimepicker();
                    var newoffset;
                    if (direction == "decrease") {
                        newoffset = scope.currentoffset - sectionlength;
                    } else if (direction == "increase") {
                        newoffset = scope.currentoffset + sectionlength;
                    }
                    if (newoffset < 0 || newoffset > timeline_width) {
                        if (newoffset < 0) {
                            newoffset = timeline_width - sectionlength;
                        } else if (newoffset > timeline_width) {
                            newoffset = 0 + sectionlength;
                        }
                        if (scope.timeframe == "am") {
                            scope.timeframe = "pm";
                        } else if (scope.timeframe == "pm") {
                            scope.timeframe = "am";
                        }
                    }
                    currenttime.css({
                        transition: "transform 0.4s ease",
                        transform: "translateX(" + (newoffset - 1) + "px)",
                    });
                    scope.currentoffset = newoffset;
                    scope.totaloffset = scope.currentoffset;
                    scope.getTime();
                };
            }
        },
    };
});

There is a function called Directive's Link. This function sets up various properties and functions in the directive's scope. And for Handling Date and time, there is a function to convert between local time and UTC time.

In the javascript code, functions like selectDate, moveForward, and moveBack handle the user's interactions with date selection and navigation. These functions update the current view date and the displayed month.

Finally, we worked on the Time Picker functionality. If the time picker is enabled, the code provides functionality to select and edit the time. The changetime and updateInputTime allow users to interact with the time picker.


Thank you for reading this article. We hope that you found the project engaging and informative.




Video of the Project

                     
                     
                 

Take This Short Survey!


Download Source Code Files

From here You can download the source code files of this Custom Date and Time Picker.
If you are new to web development, these code snippets can be helpful. If you find our blog posts valuable, we would be grateful if you could share them with others who are also interested in this topic.


Download Source Code
Please wait ...
If the download didn't start automatically, click here

ByteWebster Play and Win Offer.

PLAY A SIMPLE GAME AND WIN PREMIUM WEB DESIGNS WORTH UPTO $100 FOR FREE.

PLAY FOR FREE





Connect With Us

we would like to keep in touch with you..... Register Here.

JOIN US JOIN TELEGRAM