1

I had used the below script to hold the column headers while scrolling for SharePoint lists and document libraries as shown below.

But after adding the script , Filter dialog is also scrolling down when I scroll down the scroll bar, which is not expected .

Can any one help me what's the exact issue in below code which is making the filter dialog also scrolling , And how can I solve this

enter image description here

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
jQuery(document).ready(function(){
stickyHeaders()
})

function stickyHeaders(){
if( jQuery.inArray( "spgantt.js", g_spPreFetchKeys ) > -1){
SP.SOD.executeOrDelayUntilScriptLoaded(function () {
findListsOnPage();
}, "spgantt.js");
} else {
findListsOnPage();
}
$(window).bind('hashchange', findListsOnPage);
}

function findListsOnPage() {
var lists          = $('.ms-listviewtable')
var quickEditLists = [];
var listViews      = [];

$(lists).each(function(i){
if($(this).find('div[id^="spgridcontainer"]').length > 0 ){
quickEditLists.push($(this))
} else if( $(this).hasClass("ms-listviewgrid") == false ) {
listViews.push($(this))
}
})

if(quickEditLists.length > 0) {
SP.GanttControl.WaitForGanttCreation(function (ganttChart) {
initializeStickyHeaders(quickEditLists, "qe");
});
}

if(listViews.length > 0) {
initializeStickyHeaders(listViews, "lv");
}
}

function initializeStickyHeaders (lists, type) {
var top_old        = [], top_new        = [],
bottom_old     = [], bottom_new     = [],
stickies       = [], headers        = [],
indexOffset    = 0 ;

var style = "position:fixed;" +
"top:65px;" +
"z-index:1;" +
"background-color:white;" +
"box-shadow:3px 3px 5px #DDDDDD;" +
"display:none"

$(window).unbind('resize.' + type);
$(window).bind  ('resize.' + type, updatestickies );

$('#s4-workspace').unbind('scroll.' + type);
$('#s4-workspace').bind  ('scroll.' + type, updatestickies );

$(lists).each(function(){
headers.push($(this).find($('.ms-viewheadertr:visible')))
});

$(headers).each(function (i) {
var table = $(this).closest("table");
if(table.find("tbody > tr").length > 1) {

table.parent().find(".sticky-anchor").remove()
table.parent().find(".sticky").remove()

var anchor = table.before('<div class="sticky-anchor"></div>')
stickies.push($(this).clone(true,true).addClass("sticky").attr('style', style).insertAfter(anchor))

var tbodies = $(this).parent("thead").siblings("tbody")
if(tbodies.length > 1) {
tbodies.bind("DOMAttrModified", function(){
setTimeout(function(){
$('#s4-workspace').trigger("scroll", true)
}, 250)
})
}
} else {
headers.splice(i-indexOffset,1)
indexOffset++;
}
})

//Do it once even without beeing triggered by an event
updatestickies();

function updatestickies (event, DOMchangeEvent) {
$(headers).each(function (i) {
if(DOMchangeEvent) {
width();
return false;
}

function width() {
stickies[i].width(headers[i].width()).find('th').each(function (j) {
$(this).width(headers[i].find('th:nth-child(' + (j+1) + ')').width())
})
}

top_old[i]    = top_new[i]
top_new[i]    = Math.round($(this).offset().top - 45)
bottom_old[i] = bottom_new[i]
bottom_new[i] = Math.round(top_new[i] - 30 + $(this).closest('table').height())

stickies[i].offset({
left: Math.round(headers[i].closest("div[id^=WebPartWPQ]").offset().left)
});

if(top_old[i] >= 0 && top_new[i] <= 0 ||
bottom_old[i] <= 0 && bottom_new[i] >= 0 ||
top_old[i] === undefined && bottom_old[i] === undefined && top_new[i] < 0 && bottom_new[i] > 0 ) {
width();
stickies[i].fadeIn();
} else if (top_old[i] <= 0 && top_new[i] >= 0 || bottom_old[i] >= 0 && bottom_new[i] <= 0 ) {
stickies[i].fadeOut();
}
})
}
}

</script>

1 Answer 1

0

I know this is an old question, but hopefully, this answer can help anyone else still on SharePoint 2016.

This issue seems to be happening because the code in this solution creates a deep clone of the headers from the list view, which means that the sticky headers all have the same event handlers associated with them.

An event occurs when the sticky headers fade in that causes the filter dialog to appear, almost as if the original header has been clicked or focused. I wasn't able to track down exactly which event handler causes the filter dialog to appear, but I did manage to code a solution that checks for the sticky header-associated filter dialog and hides it if present.

This code runs after the sticky headers are faded in when updateStickies() is called after scrolling (lines 157-161 of the altered code below).

/*
 * Cody by Bijay Kumar
 * Source: https://www.enjoysharepoint.com/freeze-header-row-for-title-in-sharepoint-2013-list-view-or-document-library-on-scrolling-using-jquery/
 * Comments by Lindsey Warren
 */

jQuery(document).ready(function () {
    stickyHeaders()
})

function stickyHeaders() {
    /* 
     * Check to see if spgantt.js has been loaded. Aside: g_spPreFetchKeys
     * appears to be some "secret" SharePoint page variable that tracks what
     * SharePoint-related scripts have been loaded.
     */
    if (jQuery.inArray("spgantt.js", g_spPreFetchKeys) > -1) {
        SP.SOD.executeOrDelayUntilScriptLoaded(function () {
            findListsOnPage();
        }, "spgantt.js");
    } else {
        findListsOnPage();
    }
    // Find the lists again in case the URL has "#...." added to the end
    $(window).bind('hashchange', findListsOnPage);
}

function findListsOnPage() {
    // grab all lists -- sometimes people put multiple on a page
    var lists = $('.ms-listviewtable')
    var quickEditLists = [];
    var listViews = [];
    $(lists).each(function (i) {
        // if quickedit list
        if ($(this).find('div[id^="spgridcontainer"]').length > 0) {
            quickEditLists.push($(this))
        }
        // if normal list
        else if ($(this).hasClass("ms-listviewgrid") == false) {
            listViews.push($(this))
        }
    })
    if (quickEditLists.length > 0) {
        /*
         * WaitForGanttCreation is a "secret" method that is originally part of
         * the JSGrid library. This can get pretty deep, but its use here is quite
         * novel -- to create stickyheaders that match the quick edit grid.
         */
        SP.GanttControl.WaitForGanttCreation(function (ganttChart) {
            initializeStickyHeaders(quickEditLists, "qe");
        });
    }
    if (listViews.length > 0) {
        // just use initializeStickyHeaders for normal lists
        initializeStickyHeaders(listViews, "lv");
    }
}

function initializeStickyHeaders(lists, type) {
    var top_old = [],
        top_new = [],
        bottom_old = [],
        bottom_new = [],
        stickies = [],
        headers = [],
        indexOffset = 0;

    // styling for the sticky headers
    var style = "position:fixed;" +
        "top:65px;" +
        "z-index:1;" +
        "background-color:beige;" +
        "box-shadow:3px 3px 5px #DDDDDD;" +
        "display:none"

    /*
     * Here, the author updates or creates new event listener namespaces for
     * stickyheader functionality.
     */
    $(window).unbind('resize.' + type);
    $(window).bind('resize.' + type, updatestickies);
    $('#s4-workspace').unbind('scroll.' + type);
    $('#s4-workspace').bind('scroll.' + type, updatestickies);

    // grab the headers
    $(lists).each(function () {
        headers.push($(this).find($('.ms-viewheadertr:visible')))
    });

    // for each header...
    $(headers).each(function (i) {
        var table = $(this).closest("table");
        // if there are any rows in the table
        if (table.find("tbody > tr").length > 1) {
            // cleanup in case the code has already run on this page
            table.parent().find(".sticky-anchor").remove()
            table.parent().find(".sticky").remove()

            // now, (re)construct the sticky anchor and headers
            var anchor = table.before('<div class="sticky-anchor"></div>')
            stickies.push($(this).clone(true, true).addClass("sticky").attr('style', style).insertAfter(anchor))
            var tbodies = $(this).parent("thead").siblings("tbody")

            // in case any of the cells get modified, set a short delay then update sticky headers
            if (tbodies.length > 1) {
                tbodies.bind("DOMAttrModified", function () {
                    setTimeout(function () {
                        $('#s4-workspace').trigger("scroll", true)
                    }, 250)
                })
            }
        } else {
            // this always removes the first element from headers
            headers.splice(i - indexOffset, 1)
            indexOffset++;
        }
    })

    //Do it once even without being triggered by an event
    updatestickies();

    function updatestickies(event, DOMchangeEvent) {
        $(headers).each(function (i) {
            if (DOMchangeEvent) {
                width();
                return false;
            }

            function width() {
                /*
                 * Set the sticky width to the header width (in case it changed), then
                 * set the sticky table header widths to the corresponding header table widths
                 */
                stickies[i].width(headers[i].width()).find('th').each(function (j) {
                    $(this).width(headers[i].find('th:nth-child(' + (j + 1) + ')').width())
                })
            }

            // update the top/bottom distance from the sticky anchor
            top_old[i] = top_new[i];
            top_new[i] = Math.round($(this).offset().top - 45);
            bottom_old[i] = bottom_new[i];
            bottom_new[i] = Math.round(top_new[i] - 30 + $(this).closest('table').height());

            // match the left-offset with the left-offset of the webpart
            stickies[i].offset({
                left: Math.round(headers[i].closest("div[id^=WebPartWPQ]").offset().left)
            });

            // if scrolling down past the headers, fade in the sticky headers
            if (top_old[i] >= 0 && top_new[i] <= 0 ||
                bottom_old[i] <= 0 && bottom_new[i] >= 0 ||
                top_old[i] === undefined && bottom_old[i] === undefined && top_new[i] < 0 && bottom_new[i] > 0) {
                width();
                stickies[i].fadeIn();

                // fix for floating Filter Dialog bug
                var floatingFilterDialog = document.querySelector(".sticky .ms-core-menu-box.ms-core-menu-hasIcons.ms-core-defaultFont.ms-shadow");
                if (floatingFilterDialog) {
                    floatingFilterDialog.remove();
                }
            }
            // if scrolling back up to the headers, fade out the sticky headers
            else if (top_old[i] <= 0 && top_new[i] >= 0 || bottom_old[i] >= 0 && bottom_new[i] <= 0) {
                stickies[i].fadeOut();
            }
        })
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.