HAPI Sample - Scheduler - Sample Code for Multiple Slot Selection

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


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>

Additional Help Tutorials

Find more ways to grow on PeopleVine.

Display the total items in your shopping cart in your website header

By using the HAPI variables 0 and $0.00, you can add an always updated value within your website layout.

Posted September 12, 2019

Customize the /login with a Guest Checkout button when they're shopping in eCommerce

If you've customized your login page and are a member focused organization, but want to sell ecommerce merchandise to the public, you can setup a Guest Checkout option by following these steps.

Posted September 12, 2019

PeopleVine Check-In Tools - Featuring Fully Customizable Self-Service Check-In

See the tools available to you when checking in your members and the different data/experiences we can capture. In addition, introducing our new fully customizable self-service check-in.

Posted September 11, 2019

PeopleVine Integrates

Posted September 9, 2019

The Ultimate Guide to Importing Data into PeopleVine

You can easily import your data to PeopleVine by placing it in a CSV file and mapping the data to the appropriate fields in PeopleVine. Check out this guide for some samples and the overall data model.

Posted September 6, 2019

Prompt Questions When Checking Someone In At Your Space

Now when your members are checked in using the Control Panel, /Checkin or when scanning their QR code you can prompt a form to capture information on their visit.

Posted August 10, 2019

Ready for a Real Billing Platform (for those not using PeopleVine Billing)

Migrate to PeopleVine Billing for Memberships and streamline your business with the ultimate in "lock-down" abilities for non-payers. Get paid on-time and all the time with PeopleVine Billing.

Posted August 9, 2019

PeopleVine + SevenRooms = Hospitality Perfected

We are proud to introduce our latest update to the platform that includes a tighter integration with SevenRooms to create the ultimate hospitality experience.

Posted August 9, 2019

PeopleVine Webhooks Sync Your Data in Real-Time with Any Other System (if you needed to)

With PeopleVine Webhooks, you can sync every touchpoint with your existing systems to keep your legacy platforms updated in real-time. This article will show you how to setup a webhook and dynamically populate the data into it.

Posted July 29, 2019

Leverage "Get Items" to Automatically Issue Perks to Members + Re-Issue Perks

You can leverage the "get items" feature in order to issue perks to your members after signing up and renewing annually.

Posted July 29, 2019

Process Payment on File API Call

Learn how to connect your POS to PeopleVine and leverage our payment on file API for enabling convenience to your customers.

Posted July 27, 2019

HAPI - Setup a custom page displaying available locations based on the user's location

This code sample provides a way to automatically sort your locations by the closest distance to the user.

Posted July 22, 2019

Add Facebook Pixel Tracking to Your Website - Step by Step Guide

See how to add a Facebook Tracking Pixel to your website and start to target specific actions.

Posted July 12, 2019

New Reports + Improved Reporting Engine

Check out the new reporting tools and grid view with sorting and filtering of the live data.

Posted July 9, 2019

© PeopleVine 2019. Powered by PeopleVine. Terms of use | Privacy & cookies