I am working with bootstrap-table, which means it renders the table itself. I am trying to make the search input sticky so even if the user scroll he can still use the quick search feature without scrolling back up.
The example code can be found here: https://live.bootstrap-table.com/example/options/table-search.html
The code itself is this:
<table
id="table"
data-toggle="table"
data-search="true"
data-url="json/data1.json">
<thead>
<tr>
<th data-field="id">ID</th>
<th data-field="name">Item Name</th>
<th data-field="price">Item Price</th>
</tr>
</thead>
</table>
I've tried to do:
document.querySelector('body > div.bootstrap-table.bootstrap4 > div.fixed-table-toolbar > div').style.position = "sticky"
document.querySelector('body > div.bootstrap-table.bootstrap4 > div.fixed-table-toolbar > div').style.top = "0"
But it doesn't seem to work.
I may have killed a butterfly with a freaking nuke, but since I couldn't find a way to do it "easily" I manually cloned the input and made it fixed. Then manually checked when the original search is out of viewport in order to hide / show it. And copied the CSS from the original to make it look like it sticks.
Here's how I did it, this code is for the bootstrap table search, but you can use it for any input, I tried to leave comments so you can see where you need to edit.
HTML:
Add it anywhere inside the <body>
tag
<div id="stickySeachDiv" class="position-fixed top-0 end-0" style="z-index: 100;">
<!-- sticky search will be added by script into this div -->
</div>
CSS:
copy the properties of your search in terms of padding to create the effect like it's sticky. The hide is just so at startup it will be hidden, as in my case the original input is present on top
#stickySeachDiv {
padding-right: 2%;
display: none;
}
Javascript:
I am using auto-submit search, you can comment it out. don't forget to remove the listener too. Also, I called the CreateStickySearch from pre-bs... you can also modify that, window.onload should work too.
$("#gamesTable").one("pre-body.bs.table", createStickySearch);
function createStickySearch() {
// get hold on the input and clone it
const OriginalSearch = document.querySelector(".fixed-table-toolbar .search input");
const stickySearch = OriginalSearch.cloneNode(true);
stickySearch.addEventListener("keyup", autoSearchHandler);
stickySearch.addEventListener("search", handleStickySearch);
document.querySelector("#stickySeachDiv").appendChild(stickySearch);
// jQuery Listeners, change if you don't use jquery
$(window).on("DOMContentLoaded load resize scroll", stickySearchListener);
}
let time;
function autoSearchHandler() {
// automaticly submit the search after given time
clearTimeout(time);
time = setTimeout(() => submitStickySearch(this.value), 500);
}
function handleStickySearch() {
submitStickySearch(this.value);
}
function submitStickySearch(text) {
$("#table").bootstrapTable("refreshOptions", {
searchText: text
});
}
function revealStickySearch() {
const originalSearch = document.querySelector(".fixed-table-toolbar .search input");
const stickySearchDiv = document.querySelector("#stickySeachDiv");
const stickySearchInput = stickySearchDiv.querySelector('input');
stickySearchDiv.style.display = "block";
stickySearchInput.value = originalSearch.value;
}
function hideStickySearch() {
document.querySelector("#stickySeachDiv").style.display = "none";
}
// Code to see when it should activate, credit to https://stackoverflow.com/questions/123999/how-can-i-tell-if-a-dom-element-is-visible-in-the-current-viewport
function isElementInViewport(el) {
// Special bonus for those using jQuery
if (typeof jQuery === "function" && el instanceof jQuery) {
el = el[0];
}
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <=
(window.innerHeight ||
document.documentElement.clientHeight) /* or $(window).height() */ &&
rect.right <=
(window.innerWidth ||
document.documentElement.clientWidth) /* or $(window).width() */
);
}
let old_visible = true;
function onVisibilityChange(el, onvisible, onNotvisible) {
var visible = isElementInViewport(el);
if(visible !== old_visible) {
old_visible = visible;
visible ? onvisible() : onNotvisible();
}
}
function stickySearchListener() {
const originalSearch = document.querySelector(".fixed-table-toolbar .search input");
onVisibilityChange(originalSearch, hideStickySearch, revealStickySearch);
}
This isn't the prettiest solution, but it works, if anyone find a more elegant solution I will edit my solution.
Good luck everyone