DEV Community

Cover image for Search text and navigate -Chrome alike feature with marker locations using Angular
Nikhil Dhawan for This is Angular

Posted on

Search text and navigate -Chrome alike feature with marker locations using Angular

Photo by Aaron Burden on Unsplash

Hi All, this post is in continuation with my last post in which we have learned how to highlight text from user input, if you haven't read that you can refer to it at https://dev.to/this-is-angular/search-and-highlight-text-feature-using-angular-l98 as it is our starting part of today's task where we will make Chrome alike search and navigate feature.

Our basic code will remain the same, now we will have a bar on the right on which we will show the location as per scroller for helping to move to highlighted text from scroll bar also with arrows to navigate between those. Let us make 1 marker bar on the right side based upon the container height the location from the top, which we can get as below

marker height: number = 0;
markerTop: number = 0;
@ViewChild('textContainer') textContainer!:ElementRef;

ngAfterContentInit(): void {
    setTimeout(() => {
      const textContainerRect =
        this.textContainer.nativeElement.getBoundingClientRect();
      this.markerHeight = textContainerRect.height;
      this.markerTop = textContainerRect.top;
    }, 100);
  }

Enter fullscreen mode Exit fullscreen mode
<div *ngIf="markerHeight>0 &&markerTop>0 " class="marker" [ngStyle]="{'height':markerHeight+'px','top':markerTop+'px'}" ></div>
Enter fullscreen mode Exit fullscreen mode

Now what we have on the screen is
Image description

So now we will find a way to get the location of the highlighted text based upon the class which we attached to each highlighted text which is highlighted-text in our case, which you can choose as per your choice. We will build a function that we can call after highlights are done and save the location in an array with which we can make the ticks on the bar.

getMarkerTicks() {
    setTimeout(() => {

      this.searchElements =
        this.textContainer.nativeElement.querySelectorAll('.highlighted-text');
      const markerTicks = this.searchElements.forEach((element: any) => {


        this.markerTicks.push(
          (this.markerHeight / this.scrollHeight) *
            element.getBoundingClientRect().top
        );
      });
      this.activeIndex = 1;

      this.textContainer.nativeElement
        .querySelectorAll('.highlighted-text')[0]
        .scrollIntoView({ block: 'center', behavior: 'smooth' });
    }, 100);
  }
Enter fullscreen mode Exit fullscreen mode

And corresponding to it we can have html to create ticks as per number of highlights we have.

    <div class="markersTicks" *ngFor="let m of markerTicks" [ngStyle]="{'top':m+'px'}" ></div>

Enter fullscreen mode Exit fullscreen mode

We need now the way to show total number of highlights and navigator buttons, for which i will use disabled input and 2 arrow buttons.

  <input class="input-navigator" type="text" disabled value="{{ activeIndex + ' of '+  markerTicks.length}}" >
    <div class="nav-btns">
      <img class="nav-btn" (click)="moveToNext()" src="../assets/down-arrow.png" alt="">
      <img  class="nav-btn" (click)="moveToBack()"  src="../assets/up-arrow.png" alt="">
    </div>
Enter fullscreen mode Exit fullscreen mode

For buttons functionality we need to have functions to perform the said actions

moveToNext() {
    const highlightedSpans =
      this.textContainer.nativeElement.querySelectorAll('.highlighted-text');
    if (highlightedSpans.length > 0) {
      if (this.activeIndex === highlightedSpans.length) {
        this.activeIndex = 0;
      }
      this.activeIndex++;

      this.searchElements[this.activeIndex - 1].focus();

    }
  }
  moveToBack() {
    const highlightedSpans =
      this.textContainer.nativeElement.querySelectorAll('.highlighted-text');

    if (highlightedSpans.length > 0) {
      if (this.activeIndex === 1) {
        this.activeIndex = highlightedSpans.length + 1;
      }
      this.activeIndex--;
      this.searchElements[this.activeIndex - 1].focus();
    }
  }
Enter fullscreen mode Exit fullscreen mode

Now we are done with a fully functional app for searching and navigating between them.
done screen
Full code can be found at GitHub.
You can play with it on https://nikhild64.github.io/highlight-text-navigator/

If you liked it please share it with your friends or if any suggestions reach me out on Twitter or comment below.
Till next time Happy Learning!

Top comments (0)