XF 2.0 Sidebar jQuery toggle

Sysnative

Well-known member
Hey all,

I've created a jQuery toggle to show/hide the sidebar based on user toggle. The sidebar has been wrapped in a div element , that I'm hiding/displaying using .toggle().

The status of this is being saved for each user using the localStorage saving method, so on each page refresh the sidebar shouldn't suddenly re-appear.

The problem I'm having is that for a user who wants to hide the sidebar, the sidebar HTML is loading quicker than the jQuery, resulting in the sidebar briefly appearing and then disappearing in a glitchy/annoying way.

I tried modifying this so that the code in the <head> section changed the css of the div to be display:none; but this had the same problem - it was taking place after the HTML for the sidebar loaded, so it suddenly disappeared in a glitchy way.

Is there any way I can force the CSS change to happen before the HTML loads? Alternatively, can I update a custom setting using JS/jQuery? Any examples?

Thanks for any help!

In <head> section of PAGE_CONTAINER:
JavaScript:
    <xf:js>$(document).ready(function(){
                var block = localStorage.getItem('sidebar');
                if (block == 'true') {
                    $('#sidebar_toggle_test_id').hide();
                }
            });
    </xf:js>

In <body> section - is requested only if sidebar is enabled:

Code:
<xf:js>$(document).ready(function(){
                            $("#toggle_sidebar").click(function(){
                                $("#sidebar_toggle_test_id").toggle('slow',callbackFn());
                            });
                            function callbackFn(){
                                 localStorage.setItem('sidebar', $("#sidebar_toggle_test_id").is(":visible"));
                            }
                        });
</xf:js>
 
So I found a way to make this work - we've replaced the jQuery in the <head> section with non-jQuery <script> tags which make the CSS change before the rest of the site loads. The end result is that if the user has already hidden the sidebar, the CSS element is set to display:none before the sidebar loads.
 
So I found a way to make this work - we've replaced the jQuery in the <head> section with non-jQuery <script> tags which make the CSS change before the rest of the site loads. The end result is that if the user has already hidden the sidebar, the CSS element is set to display:none before the sidebar loads.

First, thank you for coming back and sharing your solution. Second, is this working on the latest 2.1x releases of XF? If so, can you share the code that works? I don't know enough to take your script tags comments and build it myself. Thanks.
 
This is still working in our implementation - it's possible other themes (including the default theme) might have conflicts that we didn't port into our site.

This also needs the sidebar to be setup as a widget position, with widget blocks assigned to it. Some of the HTML is probably redundant, but I made it around the time the thread was first posted, so I don't fully remember what every part of it did.

From our "PAGE_CONTAINER" template (this will probably still need some tweaking to run on your theme):

Code:
<div class="p-body-main {{ $sidebar ? 'p-body-main--withSidebar' : '' }} {{ $sideNav ? 'p-body-main--withSideNav' : '' }}">
            <xf:if is="$sideNav">
                <div class="p-body-sideNav">
                    <div class="p-body-sideNavTrigger">
                        <xf:button class="button--link" data-xf-click="off-canvas" data-menu="#js-SideNavOcm">
                            {{ $sideNavTitle ?: phrase('navigation') }}
                        </xf:button>
                    </div>
                    <div class="p-body-sideNavInner" data-ocm-class="offCanvasMenu offCanvasMenu--blocks" id="js-SideNavOcm" data-ocm-builder="sideNav">
                        <div data-ocm-class="offCanvasMenu-backdrop" data-menu-close="true"></div>
                        <div data-ocm-class="offCanvasMenu-content">
                            <div class="p-body-sideNavContent">
                                <xf:ad position="container_sidenav_above" />
                                <xf:foreach loop="$sideNav" value="$sideNavHtml">
                                    {$sideNavHtml}
                                </xf:foreach>
                                <xf:ad position="container_sidenav_below" />
                            </div>
                        </div>
                    </div>
                </div>
            </xf:if>

            <script>
                    var hideSidebar = localStorage.getItem('sidebar');
                    if (hideSidebar == 'true') {
                        document.write('<div class="p-body-content" id="p-body-content">');
                    }
                    else
                    {
                        document.write('<div class="p-body-content p-body-content-sidebar" id="p-body-content">');
                    }
            </script>
            
            <noscript><div class="p-body-content p-body-content-sidebar"></noscript>
                <xf:ad position="container_content_above" />
                <div class="p-body-pageContent">{$content|raw}</div>
                <xf:ad position="container_content_below" />
            </div>

            <xf:if is="$sidebar">

                <xf:if is="$xf.visitor.user_id">
                    <xf:js>$(document).ready(function(){
                                $("#sidebar_button").click(function(){
                                    $("#p-body-content").addClass('p-body-content-transition');
                                    $("#sidebar_full").toggle('slow',callbackFn());
                                    
                                });
                                function callbackFn(){
                                    localStorage.setItem('sidebar', $("#sidebar_full").is(":visible"));
                                    $("#sidebar_button").toggleClass('collapsed');
                                    $("#p-body-content").toggleClass('p-body-content-sidebar');
                                }
                        
                                var hideSidebar = localStorage.getItem('sidebar');
                                if (hideSidebar == 'true') {
                                    $("#sidebar_button").toggleClass('collapsed');
                                }
                                else
                                {
                                    $("#sidebar_full").css('display', 'block');
                                }
                            });
                    </xf:js>
                </xf:if>

                
                <xf:if is="$xf.visitor.user_id">
                    <script>document.write('<div id="sidebar_full">');</script>
                <xf:else />
                    <script>document.write('<div id="sidebar_full" style="display:block;">');</script>
                </xf:if>
                <noscript><div id="sidebar_full" class="no-js"></noscript>
                <div class="p-body-sidebar">
                    <xf:ad position="container_sidebar_above" />
                    <xf:foreach loop="$sidebar" value="$sidebarHtml">
                        {$sidebarHtml}
                    </xf:foreach>
                    <xf:ad position="container_sidebar_below" />
                </div>
                </div>
                <xf:if is="$xf.visitor.user_id"><div id="sidebar_button"><a href="#"></a></div></xf:if>
            </xf:if>
        </div>
 
Back
Top Bottom