All Collections
API / Customization / Advanced
HAPI - Scheduler - Sample Code for Multiple Slot Selection
HAPI - Scheduler - Sample Code for Multiple Slot Selection

Check out the sample code from our live page for booking rooms.

Jordan Gilman avatar
Written by Jordan Gilman
Updated over a week ago

CSS

    <link href="/plugins/slick/slick.css" rel="stylesheet" />
    <link href="/plugins/slick/slick-theme.css" rel="stylesheet" />
    <style>
        @media(max-width: 480px) {
            .ui-update .max-scheduler-width {
                max-width: 100px;
                overflow: hidden;
            }
        }

        .ui-update .th_time {
            font-size: 10px;
        }

        .ui-update .bookedBlock {
            width: 60px;
            overflow: hidden;
            font-size: 9px;
            max-height: 24px;
            height: 24px;
            padding: 0px;
        }

        .ui-update .timeSlot.notavailable, .ui-update .timeSlot.notavailable:hover {
            background-color: #888888;
            cursor: not-allowed;
        }

        ::-webkit-scrollbar-thumb {
            background-color: rgba(0,0,0,.24);
        }

        ::-webkit-scrollbar {
            -webkit-appearance: inherit;
            width: 8px;
        }

        .ui-update .wrapper {
            padding-top: 1em;
            padding-bottom: 1em;
        }

        .ui-update .portal-bg {
            background-color: #FFF;
        }

        .ui-update .days,
        .ui-update .timeTableWrapper {
            position: relative;
            width: 100%;
            height: 100%;
            display: inline-block;
        }

        .ui-update .input_inline {
            display: inline-block;
            width: auto;
        }

        .ui-update .input_inline {
            width: 40%;
        }

        #timeSelect .txt {
            margin: 0 8px;
        }

        #timeSelect h5,
        #locationSelect h5 {
            display: block;
        }

        .ui-update .days table {
            border-collapse: separate;
            border-spacing: 0.5em;
        }

        .ui-update .days td {
            background-color: #fff;
            padding: 8px;
            cursor: pointer;
            padding: 0.5em 1em;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -khtml-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }

            .ui-update .days td * {
                display: block;
                text-align: center;
            }

            .ui-update .days td.selected {
                box-shadow: 0 0 5px #77A331;
                z-index: 5;
            }

                .ui-update .days td.selected .hdg,
                .ui-update .days td.selected .hdg_1,
                .ui-update .days td.selected .hdg_6,
                .ui-update .days td.selected .txt,
                .ui-update .days td.selected .txt_minuscule {
                    color: #77A331;
                }

        .ui-update .times,
        .ui-update .bookSlot {
            display: none;
        }

        .ui-update .timeTableWrapper table {
            float: left;
        }

        .ui-update th {
            padding: 5px;
            height: 35px;
        }

        .ui-update td {
            padding: 5px;
            margin: 0;
            white-space: nowrap;
        }

        .ui-update .timeTableWrapper .right,
        .ui-update .days .scheduleDaysWrapper {
            overflow: auto;
        }

        .ui-update th {
            text-align: center;
        }

        .ui-update .headCol th,
        .ui-update .headCol td {
            padding-right: 10px;
        }

        .ui-update .headCol tr {
            height: 35px;
            border-right: 1px solid #f0f0f0;
            border-bottom: 1px solid #f0f0f0;
        }

        .ui-update .timeSlot {
            text-align: center;
            border: 1px solid #EEEEEE;
            cursor: pointer;
            transition: 150ms all ease-in-out;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -khtml-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            white-space: nowrap;
            min-width: 75px;
            height: 35px;
        }

            .ui-update .timeSlot:hover {
                background-color: #fbfbfb;
            }

        .ui-update .booked {
            background-color: #FEEEEB;
            border-color: #FEEEEB;
            cursor: not-allowed;
        }

            .ui-update .booked:hover {
                background-color: #FEEEEB;
                border-color: #FEEEEB;
                cursor: not-allowed;
            }

        .ui-update .blocked {
            background-color: #eefeeb;
            border-color: #eefeeb;
            cursor: not-allowed;
        }

            .ui-update .blocked:hover {
                background-color: #eefeeb;
                border-color: #eefeeb;
                cursor: not-allowed;
            }

        .ui-update .times table .selected {
            background-color: #c2d631;
            border-color: #c2d631;
        }

            .ui-update .times table .selected:hover {
                background-color: #c2d631;
            }
    </style>

HTML
(please note this is currently in ASP.NET but you can replace all with HAPI)

            <section class="component">
                <div class="component-content">

                    <div class="split split_alignBtm split_collapseOnMobile">
                        <h2 class="hdg hdg_4">Make a Reservation <%if scheduleItems.Count = 1 %>for <%=scheduleItems.Item(0).schedule_item %><%end if %></h2>
                        <!--#include file="/include/includeLoginUpdate.aspx"-->
                    </div>
                    <%if scheduleItems.Count = 1 Then %>
                    <%=scheduleItems(0).schedule_item_description %>
                    <% End if %>
                </div>
            </section>
            <section class="component">
                <div class="component-content">
                    <div class="box mix-box_outlined">
                        <div class="box-bd box-bd_inflated vr vr_x28">
                            <asp:PlaceHolder runat="server" ID="pnlSlots" Visible="false">
                                <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x6">Select a Date</h2>
                                <ul id="dateSlider" class="scheduleDays">
                                    <% Dim availSlots As Integer = 0 %>
                                    <% for i As Integer = 0 To DateDiff(DateInterval.Day, from_date, to_date) %>
                                    <% availSlots = slots.FindAll(Function(x) x.slot_start >= Convert.ToDateTime(String.Format("{0:d}", from_date.AddDays(i)) & " 12:00 AM") And x.slot_end <= Convert.ToDateTime(String.Format("{0:d}", from_date.AddDays(i)) & " 11:59 PM") And x.isAvailable).Count %>
                                    <li id="<%=String.Format("{0:MMddyyyy}", from_date.AddDays(i)) %>" data-fulldate="<%=String.Format("{0:MMMM dd yyyy}", from_date.AddDays(i)) %>">
                                        <button class="cardBtn">
                                            <span class="cardBtn-bd">
                                                <span class="cardBtn-txt cardBtn-txt_label">
                                                    <span><%=from_date.AddDays(i).ToString("dddd") %></span><br />
                                                    <span><%=MonthName(Month(from_date.AddDays(i))) %></span>
                                                    <span><%=Year(from_date.AddDays(i)) %></span>
                                                </span>
                                                <span class="cardBtn-txt cardBtn-txt_digit"><%=Day(from_date.AddDays(i)) %></span>
                                            </span>
                                            <span class="cardBtn-ft cardBtn-ft_alignRight">
                                                <span class="cardBtn-txt">
                                                    <span data-pv-element="total_slots"><%=IIf(availSlots = 0, "No", availSlots) %></span> spot<%=People_Vine___Portal.functions.returnPlural(availSlots) %> available
                                                </span>
                                            </span>
                                        </button>
                                    </li>
                                    <% next %>
                                </ul>
                                <div class="times vr vr_x8">
                                    <!-- Populate each day of slots, using the data-for to populate the day so that when you click on a day above, it opens the correct slots-->
                                    <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x3">Make Selection: <em id="selectDate"></em></h2>
                                    <div id="timeTable">
                                    </div>
                                    <% for i As Integer = 0 To DateDiff(DateInterval.Day, from_date, to_date) %>
                                    <% curDate = from_date.AddDays(i) %>
                                    <div data-for="<%=String.Format("{0:MMddyyyy}", curDate) %>" class="slotList" style="display: none;">
                                        <!-- Populates date MMMMddyyyy-->

                                        <div class="timeTableWrapper">
                                            <div class="headCol">
                                                <table>
                                                    <thead>
                                                        <th class="txt mix-txt_bold">Reserving</th>
                                                    </thead>
                                                    <tbody>
                                                        <!-- Each room gets populated as a separated row to allow the "scroll over" effect-->
                                                        <% For each si As People_Vine___Portal.api.scheduler.wi_schedule_item In scheduleItems %>
                                                        <tr>
                                                            <td class="txt mix-txt_bold max-scheduler-width">
                                                                <%=si.schedule_item %>
                                                                <%--<% If si.category_no > 0 Then %>
                                                                <br /><span class="label label-info"><%=si.category_name %></span>
                                                                <% end if %>--%>
                                                            </td>
                                                        </tr>
                                                        <% next %>
                                                    </tbody>
                                                </table>
                                            </div>
                                            <div class="right">
                                                <table>
                                                    <thead>
                                                        <!-- All times in the series get populated here as headers-->
                                                        <% tempEarliestTime = earliestTime %>
                                                        <% While tempEarliestTime < latestTime %>
                                                        <th class="th_time" id="<%=String.Format("{0:t}", tempEarliestTime) %>"><%=String.Format("{0:t}", tempEarliestTime) %></th>
                                                        <% tempEarliestTime = tempEarliestTime.AddMinutes(incrementMinutes) %>
                                                        <% end while %>
                                                    </thead>
                                                    <tbody>
                                                        <!-- Each room gets it's own row, and if booked, add class 'booked' to it-->
                                                        <!-- Start date can be in any format becauase it is not rendered on the page-->
                                                        <!-- startTime & endTime need to be in hh:mm because they get updated to the page -->
                                                        <% For each sc As People_Vine___Portal.api.scheduler.wi_schedule_item In scheduleItems %>
                                                        <tr data-room="<%=sc.schedule_item %>">
                                                            <!-- Need to loop through all slots and then if exists put block -->
                                                            <% tempEarliestTime = earliestTime %>
                                                            <% While tempEarliestTime < latestTime %>
                                                            <% curDate = Convert.ToDateTime(String.Format("{0:d}", curDate) & " " & String.Format("{0:t}", tempEarliestTime)) %>
                                                            <% slot = slots.Find(Function(x) x.slot_start >= curDate And x.slot_end <= curDate.AddMinutes(sc.block_duration) And x.schedule_item_no = sc.schedule_item_no) %>
                                                            <% if slot Is Nothing Then %>
                                                            <td class="timeSlot notavailable booked">&nbsp;</td>
                                                            <% else %>
                                                            <td data-fee="<%=slot.slot_fee %>" data-room="<%=sc.schedule_item %>" data-starttime="<%=String.Format("{0:t}", slot.slot_start) %>" data-endtime="<%=String.Format("{0:t}", slot.slot_end) %>" data-startdate="<%=String.Format("{0:d}", slot.slot_start) %>" data-duration="<%=sc.block_duration %>" data-roomno="<%=sc.schedule_item_no %>" data-slotno="<%=slot.schedule_slot_no %>" class="timeSlot <%=IIf(slot.isAvailable, IIf(sc.canBook, "", "blocked"), "booked") %>" <%=IIf(Not slot.isAvailable And sc.canBook And sc.visibility <> "public", "title=""" & slot.customer.company_name & " (" & slot.customer.first_name & ")""", "") %>>
                                                                <% If Not slot.isAvailable And sc.canBook And sc.visibility <> "public" And slot.customer.customer_no > 0 Then %>
                                                                <div class="bookedBlock">
                                                                    <%=slot.customer.company_name %><br />
                                                                    <%=slot.customer.first_name %>&nbsp; <%=IIf(slot.customer.last_name.Length > 1, Left(slot.customer.last_name, 1), "") %>
                                                                </div>
                                                                <% else %>
                                                                <% if slot.slot_fee > 0 Then %>
                                                                <%=String.Format("{0:c}", slot.slot_fee) %>
                                                                <% else %>
                                                                        &nbsp;
                                                                    <% end if %>
                                                                <% end if %>
                                                            </td>
                                                            <% end if %>
                                                            <% tempEarliestTime = tempEarliestTime.AddMinutes(incrementMinutes) %>
                                                            <% end while %>
                                                        </tr>
                                                        <% next %>
                                                    </tbody>
                                                </table>
                                            </div>
                                        </div>
                                    </div>
                                    <% Next %>
                                </div>
                                <div class="bookSlot" id="bookSlot">
                                    <h1 class="hdg hdg_5">Confirm Selection:</h1>
                                    <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x3"><em><span id="dateSelection">January 1st, 2016</span> <span id="roomName">Example Room</span> <span id="roomStartTime">12:00PM</span> – <span id="roomEndTime">12:30PM</span></em> <span id="roomCost">$0.00</span></h2>
                                    <ul class="split split_alignBtm split_collapseOnMobile split_basisRight">
                                        <li>
                                            <span class="txt txt_feature">Please confirm the date, time and item you are booking is accurate.  On the next step, you will be taken to confirm your reservation.</span>
                                        </li>
                                        <li>
                                            <a href="/reservation" class="btn btn_hasIcon" id="bookNowBtn" onclick="myApp.showPleaseWait();">Continue<svg class="icon"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/media/svg/defs.svg#icon_caretRightHeavy"></use></svg>
                                            </a>
                                        </li>
                                    </ul>
                                </div>
                            </asp:PlaceHolder>
                            <asp:PlaceHolder runat="server" ID="pnlNoSlots" Visible="false">
                                <h2 class="hdg hdg_4">Sorry, we don't currently have any availability at this time.</h2>
                            </asp:PlaceHolder>
                        </div>
                    </div>
                </div>
            </section>
            <section class="component component_loose">
                <div class="component-content">
                    <div class="box mix-box_outlined">
                        <div class="box-bd box-bd_inflated">
                            <div class="split split_basisRight split_collapseOnMobile">
                                <h3 class="hdg hdg_6 mix-hdg_brandCallout">When booking, keep in mind these restrictions:</h3>
                                <div>
                                    <%if scheduleItems.Count = 1 Then %>
                                    <% if scheduleItems(0).time_between > 0 Or scheduleItems(0).max_blocks > 0 Then %>
                                    <ul class="blocks blocks_4to3to2to1 blocks_equalHeight">
                                        <% if scheduleItems(0).time_between > 0 Then %>
                                        <li>
                                            <a class="cardBtn">
                                                <span class="cardBtn-bd">
                                                    <span class="cardBtn-txt cardBtn-txt_label">Time Between<br />
                                                        Reservations
                                                    </span>
                                                    <span class="cardBtn-txt cardBtn-txt_digit"><%=IIf(scheduleItems(0).time_between > 1440, scheduleItems(0).time_between / 1440, IIf(scheduleItems(0).time_between > 60, scheduleItems(0).time_between / 60, scheduleItems(0).time_between)) %></span> <small><%=IIf(scheduleItems(0).time_between > 1440, "days", IIf(scheduleItems(0).time_between > 60, "hours", "minutes")) %></small>
                                                </span>
                                            </a>
                                        </li>
                                        <% End if %>
                                        <% If scheduleItems(0).max_blocks > 0 Then %>
                                        <li>
                                            <a class="cardBtn">
                                                <span class="cardBtn-bd">
                                                    <span class="cardBtn-txt cardBtn-txt_label">Max Slots<br />
                                                        Per Booking
                                                    </span>
                                                    <span class="cardBtn-txt cardBtn-txt_digit"><%=scheduleItems(0).max_blocks %></span>
                                                    <small><%=IIf(scheduleItems(0).block_duration > 1440, scheduleItems(0).block_duration / 1440, IIf(scheduleItems(0).block_duration > 60, scheduleItems(0).block_duration / 60, scheduleItems(0).block_duration)) %> minutes each</small>
                                                </span>
                                            </a>
                                        </li>
                                        <% end if %>
                                    </ul>
                                    <% else %>

                                    <% End if %>
                                    <% else %>
                                    <ul class="blocks blocks_4to3to2to1 blocks_equalHeight">
                                        <% If maxSlots > 0 Then %>
                                        <li>
                                            <a class="cardBtn">
                                                <span class="cardBtn-bd">
                                                    <span class="cardBtn-txt cardBtn-txt_label">Max Slots<br />
                                                        Per Booking
                                                    </span>
                                                    <span class="cardBtn-txt cardBtn-txt_digit"><%=maxSlots %></span>
                                                    <small><%=IIf(incrementMinutes > 1440, incrementMinutes / 1440, IIf(incrementMinutes > 60, incrementMinutes / 60, incrementMinutes)) %> minutes each</small>
                                                </span>
                                            </a>
                                        </li>
                                        <% end if %>
                                    </ul>
                                    <% End if %>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
            <section class="component component_loose">
                <div class="component-content">

                    <div class="box mix-box_outlined">
                        <div class="box-bd box-bd_inflated vr">
                            <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x6">Filter</h2>
                            <ul class="gridList">
                                <li class="gridList-item gridList-item_7of16 gridList-item_tight" style="<%=iif(request("type") = "calendar", "display:none;", "")%>">
                                    <ul class="gridList-item-subGroup">
                                        <li>
                                            <span class="fieldset">
                                                <label class="fieldset-label fieldset-label_isHidden" for="<%=sfrom_date.ClientID %>">start date</label>
                                                <span class="fieldset-input">
                                                    <asp:TextBox runat="server" ID="sfrom_date" placeholder="MM/DD/YYYY" CssClass="js-datepicker" />
                                                </span>
                                            </span>
                                        </li>
                                        <li>
                                            <span class="fieldset">
                                                <label class="fieldset-label fieldset-label_isHidden" for="<%=sto_date.ClientID %>">end date</label>
                                                <span class="fieldset-input">
                                                    <asp:TextBox runat="server" ID="sto_date" placeholder="MM/DD/YYYY" CssClass="js-datepicker" />
                                                </span>
                                            </span>
                                        </li>
                                    </ul>
                                </li>
                                <li class="gridList-item gridList-item_7of16 gridList-item_tight">
                                    <span class="fieldset">
                                        <label class="fieldset-label" for="<%=schedule_item_no.ClientID %>">or filter</label>
                                        <span class="fieldset-input">
                                            <asp:DropDownList runat="server" ID="schedule_item_no" />
                                        </span>
                                    </span>
                                </li>
                                <li class="gridList-item gridList-item_2of16 gridList-item_tight">
                                    <span class="fieldset">
                                        <label class="fieldset-label">&nbsp;</label>
                                        <asp:Button runat="server" ID="btnsub" Text="Apply" CssClass="btn mix-btn_stretch" OnClick="btnsub_Click" OnClientClick="myApp.showPleaseWait();" />

                                    </span>
                                </li>
                                <li class="gridList-item" style="<%=iif(request("type") = "calendar", "display:none;", "")%>">
                                    <asp:RadioButtonList runat="server" ID="filterDate" CssClass="hList tick tick_bubble" RepeatLayout="UnorderedList" AutoPostBack="true" OnSelectedIndexChanged="filterDate_SelectedIndexChanged">
                                        <asp:ListItem Value="today">Today</asp:ListItem>
                                        <asp:ListItem Value="tomorrow">Tomorrow</asp:ListItem>
                                        <asp:ListItem Value="this week">This Week</asp:ListItem>
                                        <asp:ListItem Value="next week">Next Week</asp:ListItem>
                                    </asp:RadioButtonList>
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
            </section>

Javascript

    <script>window.jQuery || document.write('<script src="/assets/jQuery/default/jquery.min.js">\x3C/script>')</script>
    <script src="/scripts/vendor/fullcalendar/moment.min.js"></script>
    <script src="/plugins/slick/slick.min.js"></script>
    <script src="/scripts/components/schedulerMulti.js"></script>
    <script>
        //JS init for slider (init is for reference only - page is not loading Slick Slider plugin: http://kenwheeler.github.io/slick/)
        var MAX_SLOTS = 10 //make dynamic based on available schedulers;
        var loadSlick = function () {
            var selector = '#dateSlider';
            var config = {
                centerPadding: '60px',
                slidesToShow: 7,
                arrows: true,
                infinite: false,
                responsive: [
                    {
                        breakpoint: 979,
                        settings: {
                            slidesToShow: 7
                        }
                    },
                    {
                        breakpoint: 767,
                        settings: {
                            slidesToShow: 3
                        }
                    },
                    {
                        breakpoint: 480,
                        settings: {
                            slidesToShow: 1
                        }
                    }
                ]
            };
            $(selector).slick(config);
        };

        $(document).ready(function () {
            //new DatepickerHelper('.js-datepicker', { setDate: new Date(), minDate: new Date(1900, 1, 1) });
            var Sch = scheduler(MAX_SLOTS);
            Sch.init();
            loadSlick();

            $("#sfrom_date").datepicker({
                defaultDate: "+1d",
                changeMonth: false,
                numberOfMonths: 3,
                minDate: "+0d",
                maxDate: "+360d",
                onClose: function (selectedDate) {
                    $("#sto_date.ClientID").datepicker("option", "minDate", selectedDate);
                }
            });
            $("#sto_date").datepicker({
                defaultDate: "+3d",
                changeMonth: false,
                numberOfMonths: 3,
                minDate: "+1d",
                maxDate: "+360d",
                onClose: function (selectedDate) {
                    $("#sfrom_date").datepicker("option", "maxDate", selectedDate);
                }
            });
        });
    </script>

Did this answer your question?