Search code examples
jquerysearchhighlight

Mark.js not scrolling to next result when inside a scrollable div/table


I am using minicss framework with jquery and mark.js to build a responsive, one-page, searchable owner's manual.

I am trying to use the mark.js script with search bar highlighting to cycle through results on one single page.

Everything works fine until it finds a result that is INSIDE one of the scrollable table divs.

Similar to this example: https://jsfiddle.net/julmot/973gdh8g/

and here is the code I am using in header for the mark.js :

window.onload=function(){

$(function() {

  // the input field
  var $input = $("input[type='search']"),
    // clear button
    $clearBtn = $("button[data-search='clear']"),
    // prev button
    $prevBtn = $("button[data-search='prev']"),
    // next button
    $nextBtn = $("button[data-search='next']"),
    // the context where to search
    $content = $(".content2"),
    // jQuery object to save <mark> elements
    $results,
    // the class that will be appended to the current
    // focused element
    currentClass = "current",

    // top offset for the jump (the search bar)
    offsetTop = 70,
    // the current index of the focused element
    currentIndex = 0;

  /**
   * Jumps to the element matching the currentIndex
   */
  function jumpTo() {
    if ($results.length) {
      var position,
        $current = $results.eq(currentIndex);
      $results.removeClass(currentClass);

      if ($current.length) {
        $current.addClass(currentClass);


          position = $current.offset().top - offsetTop;
        //window.scrollTo(0, position);

      //var currentmark = getElementsByClassName('current');

          //var tab = getElementsByClassName('scrollable striped');
         var doc = document.getElementById('doc-content');

         var element = document.getElementsByClassName('current');



          //var menu = getElementById('nav-drawer');

            //menu.scrollTo(0, position);
          //tab.scrollTo(0, position);
            //tab.scrollTo(0, position);

    element.scrollTo(0, position);

          doc.scrollTo(0, position);


        //element.scrollIntoView(true);  

         //window.scrollTo(0, position);



      }
    }
  }

  /**
   * Searches for the entered keyword in the
   * specified context on input
   */
  $input.on("input", function() {
    var searchVal = this.value;
    $content.unmark({
      done: function() {
        $content.mark(searchVal, {
          separateWordSearch: true,

          done: function() {
            $results = $content.find("mark");
            currentIndex = 0;
            jumpTo();
          }
        });
      }
    });
  });

  /**
   * Clears the search
   */
  $clearBtn.on("click", function() {
    $content.unmark();
    $input.val("").focus();
  });

  /**
   * Next and previous search jump to
   */
  $nextBtn.add($prevBtn).on("click", function() {
    if ($results.length) {
      currentIndex += $(this).is($prevBtn) ? -1 : 1;
      if (currentIndex < 0) {
        currentIndex = $results.length - 1;
      }
      if (currentIndex > $results.length - 1) {
        currentIndex = 0;
      }
      jumpTo();
    }
  });
});


    }

I have tried adding

var element = document.getElementsByClassName('current');

element.scrollTo(0, position); 

in the jumpto() script, right BEFORE it scrolls the main window, however it doesn't seem to work for some reason.


Solution

  • edited, you need to scroll the table find it parent using .closest() and the demo

    function jumpTo() {
      if ($results.length) {
        var position,
          $current = $results.eq(currentIndex);
        $results.removeClass(currentClass);
        if ($current.length) {
          $current.addClass(currentClass);
          var parent = $current.closest('table')
          if (parent.length) {
            $('html').scrollTop(parent.offset().top - offsetTop)
            parent.scrollTop(parent.scrollTop() - parent.offset().top + $current.offset().top);
          }
          else {
            $('html').animate({
              scrollTop: $current.offset().top - offsetTop
            }, 300);
          }
        }
      }
    }