Search code examples
htmljquerycssgrid

HTML challenge - Time slots


I need to build something like in the following:

enter image description here

This is the structure I built so far:

https://codepen.io/orassayag/pen/XWMxWPp

But I have difficult times to build the grid.

This is the code:

<!doctype html>

<html lang="en">

<head>
    <meta charset="utf-8">

    <title>The HTML5 Herald</title>
    <meta name="description" content="The HTML5 Herald">
    <meta name="author" content="SitePoint">

</head>

<body>
    <div class="devices-container">
        <div class="index">
            <div class="index-box head">
                Device / Time
            </div>
            <div class="index-box">
                Device 1
            </div>
            <div class="index-box">
                Device 1
            </div>
            <div class="index-box">
                Device 1
            </div>
            <div class="index-box">
                Device 1
            </div>
            <div class="index-box">
                Device 1
            </div>
            <div class="index-box tail">
                Device 1
            </div>
        </div>
        <div class="timeline">
            <div id="timetable">
                <div class="timetable_content">
                    <ul class="hours">
                        <li data-hour="00">
                            <div class="hour-container">
                                <div class="time1">00:00</div>
                                <div class="time2">00:30</div>
                            </div>
                        </li>
                        <li data-hour="01">
                            <div class="hour-container">
                                <div class="time1">01:00</div>
                                <div class="time2">01:30</div>
                            </div>
                        </li>
                        <li data-hour="02">
                            <div class="hour-container">
                                <div class="time1">02:00</div>
                                <div class="time2">02:30</div>
                            </div>
                        </li>
                        <li data-hour="03">
                            <div class="hour-container">
                                <div class="time1">03:00</div>
                                <div class="time2">03:30</div>
                            </div>
                        </li>
                        <li data-hour="04">
                            <div class="hour-container">
                                <div class="time1">04:00</div>
                                <div class="time2">04:30</div>
                            </div>
                        </li>
                        <li data-hour="05">
                            <div class="hour-container">
                                <div class="time1">05:00</div>
                                <div class="time2">05:30</div>
                            </div>
                        </li>
                        <li data-hour="06">
                            <div class="hour-container">
                                <div class="time1">06:00</div>
                                <div class="time2">06:30</div>
                            </div>
                        </li>
                        <li data-hour="07">
                            <div class="hour-container">
                                <div class="time1">07:00</div>
                                <div class="time2">07:30</div>
                            </div>
                        </li>
                        <li data-hour="08">
                            <div class="hour-container">
                                <div class="time1">08:00</div>
                                <div class="time2">08:30</div>
                            </div>
                        </li>
                        <li data-hour="09">
                            <div class="hour-container">
                                <div class="time1">09:00</div>
                                <div class="time2">09:30</div>
                            </div>
                        </li>
                        <li data-hour="10">
                            <div class="hour-container">
                                <div class="time1">10:00</div>
                                <div class="time2">10:30</div>
                            </div>
                        </li>
                        <li data-hour="11">
                            <div class="hour-container">
                                <div class="time1">11:00</div>
                                <div class="time2">11:30</div>
                            </div>
                        </li>
                        <li data-hour="12">
                            <div class="hour-container">
                                <div class="time1">12:00</div>
                                <div class="time2">12:30</div>
                            </div>
                        </li>
                        <li data-hour="13">
                            <div class="hour-container">
                                <div class="time1">13:00</div>
                                <div class="time2">13:30</div>
                            </div>
                        </li>
                        <li data-hour="14">
                            <div class="hour-container">
                                <div class="time1">14:00</div>
                                <div class="time2">14:30</div>
                            </div>
                        </li>
                        <li data-hour="15">
                            <div class="hour-container">
                                <div class="time1">15:00</div>
                                <div class="time2">15:30</div>
                            </div>
                        </li>
                        <li data-hour="16">
                            <div class="hour-container">
                                <div class="time1">16:00</div>
                                <div class="time2">16:30</div>
                            </div>
                        </li>
                        <li data-hour="17">
                            <div class="hour-container">
                                <div class="time1">17:00</div>
                                <div class="time2">17:30</div>
                            </div>
                        </li>
                        <li data-hour="18">
                            <div class="hour-container">
                                <div class="time1">18:00</div>
                                <div class="time2">18:30</div>
                            </div>
                        </li>
                        <li data-hour="19">
                            <div class="hour-container">
                                <div class="time1">19:00</div>
                                <div class="time2">19:30</div>
                            </div>
                        </li>
                        <li data-hour="20">
                            <div class="hour-container">
                                <div class="time1">20:00</div>
                                <div class="time2">20:30</div>
                            </div>
                        </li>
                        <li data-hour="21">
                            <div class="hour-container">
                                <div class="time1">21:00</div>
                                <div class="time2">21:30</div>
                            </div>
                        </li>
                        <li data-hour="22">
                            <div class="hour-container">
                                <div class="time1">22:00</div>
                                <div class="time2">22:30</div>
                            </div>
                        </li>
                        <li data-hour="23">
                            <div class="hour-container last">
                                <div class="time1">23:00</div>
                                <div class="time2">23:30</div>
                            </div>
                        </li>
                    </ul>
                    <ul class="timeslots">
                        <li>
                            <div class="timeslot" data-hour-start="00" data-hour-end="00.5"></div>
                        </li>
                        <li>
                            <div class="timeslot" data-hour-start="00.5" data-hour-end="01"></div>
                        </li>
                        <li>
                            <div class="timeslot" data-hour-start="18" data-hour-end="19"></div>
                        </li>
                        <li>
                            <div class="timeslot" data-hour-start="07.5" data-hour-end="10"></div>
                        </li>
                        <li>
                            <div class="timeslot" data-hour-start="23.5" data-hour-end="24"></div>
                        </li>
                        <li>
                            <div class="timeslot" data-hour-start="23.5" data-hour-end="24"></div>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</body>
<style type="text/css">
    .devices-container {
        display: flex;
        flex-direction: row;
    }

    .index-box {
        height: 70px;
        display: flex;
        align-items: stretch;
        flex-wrap: nowrap;
        align-content: center;
        flex-direction: row;
        justify-content: center;
        line-height: 4;
        border: 1px #cccccc solid;
        border-right: 0px;
        border-bottom: 0px;
        padding: 1em;
        padding-top: 0px;
        padding-bottom: 0px;
    }

    .index-box.head {
        line-height: 3;
        height: 50px;
        border-right: 0px;
        border-bottom: 0px;
    }

    .index-box.tail {
        border-bottom: 1px #cccccc solid;
    }

    #timetable {
        width: 100%;
        height: auto;
        max-width: 768px;
        overflow-y: hidden;
        border: 1px solid #cccccc;
    }

    #timetable ul {
        padding: 0;
        list-style: none;
        margin: 0;
    }

    .timetable_content {
        width: 2640px;
    }

    .device {
        display: flex;
        flex-direction: row;
        width: 110px;
        text-align: center;
    }

    .hours {
        width: 2640px;
        max-height: 50px;
        overflow: hidden;
    }

    .hours li {
        width: 110px;
        text-align: center;
        float: left;
        display: inline-block;
        padding: 0px;
    }

    .hour-container {
        width: 100%;
        display: flex;
        flex-direction: row;
        justify-content: space-around;

    }

    .hours li div {
        width: 100%;
        height: 56px;
        border: 1px solid #cccccc;
        border-top: 0px;
        line-height: 3;
        border-left: 0px;
        border-right: 0px;
        font-size: .8em;
    }

    .hours li div .time1 {
        border-left: 0px solid #cccccc;
        border-right: 1px solid #cccccc;
        border-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 45%, rgba(0, 0, 0, 1) 45%, rgba(0, 0, 0, 1) 90%, rgba(0, 0, 0, 0) 90%);
        border-image-slice: 1;
    }

    .hours li div .time2 {
        border-left: 0px solid #cccccc;
        border-right: 1px solid #cccccc;
        border-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 45%, rgba(0, 0, 0, 1) 45%, rgba(0, 0, 0, 1) 90%, rgba(0, 0, 0, 0) 90%);
        border-image-slice: 1;
    }

    .hours li div.last .time2 {
        border-left: 0px solid #cccccc;
        border-right: 0px solid #cccccc;
    }

    .timeslots {
        width: 2640px;
    }

    .timeslots li {
        border-top: 1px solid #cccccc;
    }

    .timeslots .timeslot {
        height: 70px;
        background: #ff0000;
        display: block;
    }
</style>
<script>
    (function() {
        var firstHoursLiElWidth = 110;
        var hoursItems = 2640;
        const halfHourPx = 55;

        const timeSlots = document.querySelectorAll('.timeslots li');
        for (let i = 0; i < timeSlots.length; i++) {
            var element = timeSlots[i].querySelector('.timeslot'),
                startDate = element.getAttribute('data-hour-start');
                endDate = element.getAttribute('data-hour-end');
            let isHalf = false;
            let staticStart = startDate;
            if (startDate.toString().indexOf('.5') > -1) {
                isHalf = true;
                staticStart = startDate.toString().replace('.5', '');
            }
            var hoursInProject = (endDate - startDate);
            var startDateEl = document.querySelectorAll(".hours li[data-hour='" + staticStart + "']")[0].getBoundingClientRect().left - 133;
            element.style.marginLeft = `${isHalf ? halfHourPx + startDateEl : startDateEl}px`;
            element.style.width = `${firstHoursLiElWidth * hoursInProject + (hoursInProject / 1.5)}px`;
        }
    })();
</script>

</html>

How can I build a grid that I can add rows dynamically and whey will fit the time, and the first column will be sticky, and the rest of the time slots will be horizontal scroll?
Can someone please help me?
Thanks.

UPDATE 1 Found something fit to my needs, but I can't do it in jQuery :( https://codepen.io/frlinw/pen/JMvXEy

UPDATE 2 I managed to do some improvements in the code, but I'm missing the border between the slots. Any idea how to work around it?


Solution

  • I managed to solve the challenge.
    I rebuilt the project completely, made it with divs and flexbox, and filled the slots by using simple JavaScript (instead of using margin-left in the SCSS).
    Also, I built the project in React.

    If anyone is interested, here are the final results:
    https://github.com/orassayag/job-interview-exercises/tree/master/jobs/job-13/project