bootstrap-table icon indicating copy to clipboard operation
bootstrap-table copied to clipboard

An option to make the search bar sticky when scroll

Open eliezra236 opened this issue 3 years ago • 3 comments

Description

In large tables, it would be really helpful to pin the search bar, that way people won't be forced to use CTRL+F, which is really annoying to use on mobile. I've posted in stackoverflow question to try and find a workaround for the time being: https://stackoverflow.com/questions/67858026/change-an-element-to-be-sticky-after-it-render-making-search-input-sticky

But that feature could really be helpful

eliezra236 avatar Jun 06 '21 10:06 eliezra236

I found a workaround to manually create another search and set it to work the same. I updated it on the stack-overflow I made at the post, but I keep the suggestion open because I think it can be better impletemented

eliezra236 avatar Jun 10 '21 09:06 eliezra236

Awesome thanks! Can you provide an example with your workaround?

djhvscf avatar Jul 04 '21 02:07 djhvscf

Awesome thanks! Can you provide an example with your workaround?

I posted it on stack overflow that I mentioned in the post, but I will post it here as well. A working example can be found on my website - https://www.gamepasscompare.com/games/AllGames

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.

eliezra236 avatar Jul 04 '21 17:07 eliezra236