While working on the mobile site, I had a few challenges with the Kendo responsive panel that I solved with the blog today, and wanted to make a post about it as I could not find any other solution on the web. I ran into someone posting the same scrolling question as I was looking to solve on stack overflow, but could not find anything else on the web.

The responsive panel is used to provide a slide-out menu on mobile devices when you click on what is commonly known as a 'hamburger. The panel is used in responsive web design and is triggered when the device reaches a certain minimum screen width. Here is the code that I developed for this blog:

view plain about
1<nav id="sidebarPanel" class="k-content">
2    <!---Suppply the sideBarType argument before loading the side bar--->
3    <cfset sideBarType = "panel">
4    <cfinclude template="includes/layers/sidebar.cfm">
5</nav><!---<nav id="sidebar">--->
7<!--- This script must be placed underneath the layer that is being used in order to effectively work as a flyout menu.--->
9    $("#sidebarPanel").kendoResponsivePanel({
10        breakpoint: 1280,
11        orientation: "left",
12        autoClose: true
13        })
14        .on("click", "a", function(e) {
15            $("#sidebarPanel").kendoResponsivePanel("close");
16    });

There were several challenges that I ran into when developing this.

First, I tried to use the same div element that I use on the right side of the page to hold the various widgets, such as the calendar, subscribe, recent posts, etc. However, I noticed that if I tried to use the same div for the responsive menu, I could no longer apply certain css properties to the panel, and it was stuck at the top of the page.

To solve this, I used a different div at the end of the application to serve as the responsive panel, duplicated the logic from the right column, and put it into the new panel at the end of the page. I also created a script to show the new responsive panel when the screen size hit the breakpoint setting (1280 pixels), and hid the original div that is on the right column. Here is the relevant portions of the code:

view plain about
1// Handle the sidebar and the sideBarPanels
2    if (windowWidth <= 1280){
3        // Hide the sidepanel (the responsive panel will takeover here).
4        $( "#sidebar" ).hide();
5        // Show the responsive panel
6        $( "#sidebarPanel" ).show();
7    } else {
8        // Show the sidebar, and hide the responsive panel
9        $( "#sidebar" ).show();
10        $( "#sidebarPanel" ).hide();
11    }

Second, the hamburger showed up, but it closed as soon as I tried to open it. I found the following solution while searching the web:

view plain about
1// Important note: this is a workaround with a google chrome bug and mobile devices.
2// This prevents the following error: "Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive."
3// See https://github.com/telerik/kendo-ui-core/issues/3556
4$(".k-rpanel-toggle").on("touchend", function(e) {
5     e.preventDefault();

Third, I ran into problems where to put the resonsivePanel initiation script. I found out that it must be at underneath the actual element that it will be placed into.

It now works, however, there is a big problem. I could not scroll down the responsive panel when it was triggered. It just stayed in a fixed position and only showed the top part of the page. I looked everywhere in the Kendo site, and then on the internet, looking for some arcane argument that I could use, such as scrollable: true, but couldn't find any. I then looked at the similar jQuery UI menu, and inspected Telerik's production page which has a responsive panel and found that they both used the css declaration: position: absolute;

view plain about
1position: absolute;

Fourth. Ok, that fixed that problem, but now the div layer disappeared at the bottom of the page. I tried setting height to 100%, but that failed too. So I looked at both jQuery and Kendo's panels again, and noticed that they also used: height: auto;

view plain about
1height: auto;
Also, use the autoclose argument to be false on the responsive panel widget, otherwise you won't be able to able to keep the layer open when scrolling past the bottom of the first page. That worked! The panel can be scrolled now.

The final working code is pasted below:


view plain about
1/* The side bar panel is essentially a duplicate of the sidebar div, however, it is a responsive panel used when the screen size gets small. */
2#sidebarPanel {
3/* We are going to eliminate this sidebar for larger devices, and activate it when the screen size gets to a certain size. */
4display: none;
5/* Note: the panel will not scroll with the blog content unless there is a css position: absolute. */
6position: absolute;
7margin: 0;
8/* Apply more padding to the right to keep things uniform. */
9padding: 20px 40px 20px 20px;
10width: 45%;
11/* Note: if you don't set 'height: auto', the panel will not be displayed below the bottom of the page. */
12height: auto;
13vertical-align: top;
14overflow: visible;
15border-right: thin;
17/* Put a drop shadow on the panel when it is expanded. */
18#sidebarPanel.k-rpanel-expanded {
19 box-shadow: 0 0 10px rgba(0,0,0,.3);
20 }
view plain about
1<!---This is the sidebar responsive navigation panel that is triggered when the screen gets to a certain size. It is a duplicated of the sidebar div above, however, I can't properly style the sidebar the way that I want to within the blog content, so it is duplicated without the styles here.--->
3<!--- Side bar is to the right of the main panel container. It is also used as a responsive panel below when the screen size is small. --->
4<nav id="sidebarPanel" class="k-content">
5<!---Suppply the sideBarType argument before loading the side bar--->
6<cfset sideBarType = "panel">
7<cfinclude template="includes/layers/sidebar.cfm">
8</nav><!---<nav id="sidebar">--->
view plain about
1<!--- This script must be placed underneath the layer that is being used in order to effectively work as a flyout menu.--->
2    $("#sidebarPanel").kendoResponsivePanel({
3        breakpoint: 1280,
4        orientation: "left",
5        autoClose: false // set this to false if you want the layer to stay up when you want to sroll down.
6        })
7        .on("click", "a", function(e) {
8            $("#sidebarPanel").kendoResponsivePanel("close");
9    });
11// Important note: this is a workaround with a google chrome bug and mobile devices.
12// This prevents the following error: "Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive."
13// See https://github.com/telerik/kendo-ui-core/issues/3556
14    $(".k-rpanel-toggle").on("touchend", function(e) {
15        e.preventDefault();
16    });