← Snippets - Script

Anchor to Things

Clients often request for anchor links to automatically open tabs or accordions. This has changed A LOT throughout the years, so the how-to will be displayed by the version of bootstrap it works with, starting with the most recent.

With most/all of these, the console logs from debugging have been left in place, but commented out, so they can be uncommented for testing if needed.

Bootstrap 5

Probably needs work/refining/refactoring, but worked on Shore United’s remake.

How To

banno-functions.js

Add the following into the methods section of the banno-functions.js file.

  accordionTabAnchor: function() {
      // console.log('inside top of accordiontabanchor function')
      let hash = window.location.hash.substring(1);
      // Determine if hash is going to tab or accordion
      if (document.querySelectorAll('.nav.nav-tabs').length > 0) {
        //tabs exist, make sure hash link is within tab
        let closestPaneId = document.getElementById(hash).closest('.tab-pane');
        if (closestPaneId) {
          // console.log('anchor tag with ID same as # in URL has been found')
          let closestPaneIdLabel = closestPaneId.getAttribute('aria-labelledby');
          document.getElementById(closestPaneIdLabel).click();
          const scrollIntoViewWithOffset = (selector, offset) => {
            setTimeout(function() {
              window.scrollTo({
                behavior: 'smooth',
                top: document.getElementById(selector).getBoundingClientRect().top - document.body.getBoundingClientRect().top - offset,
              })
            },1000)
          }
          scrollIntoViewWithOffset(hash,150);
        } else {
          // console.log('hash link exists but is not within tab');
        }
      } else {
        // console.log('no tabs on the page');
      }
      // URL includes link to accordion
      if (document.querySelectorAll('.accordion').length > 0) {
        let closestAccordionId = document.getElementById(hash).closest('.collapse');
        if (closestAccordionId) {
          // console.log('anchor tag with ID same as # in URL has been found')
          let closestAccordionIdLabel = closestAccordionId.getAttribute('aria-labelledby');
          document.getElementById(closestAccordionIdLabel).click();
          const scrollIntoViewWithOffset = (selector, offset) => {
            setTimeout(function() {
              window.scrollTo({
                behavior: 'smooth',
                top: document.getElementById(selector).getBoundingClientRect().top - document.body.getBoundingClientRect().top - offset,
              })
            },1000)
          }
          scrollIntoViewWithOffset(hash,150);
        } else {
          // console.log('hash link exists but is not within tab');
        }
      } else {
        // console.log('no accordions on the page');
      }

      if (document.querySelectorAll('.modal').length > 0) {
        // console.log("there are modals");
        document.querySelectorAll('.modal').forEach(function(modal) {
          if (hash) {
            let anchor = modal.querySelector('a#' + hash);
            if (anchor && modal.contains(anchor)) {
              const modalInit = new bootstrap.Modal(modal)
              modalInit.show();
            } else {
              // console.log('hash link exists but is not within modal');
            }
          }
        })
      }
    },

scripts.js

Within the window.addEventListener('load', function() { section (scripts when the page is fully loaded), inside of the “if not in CMS” function, put this to call the method whenever a link with an anchor is clicked.

//Open accordion on click of anchor link
    if(window.location.hash) {
      banno.methods.accordionTabAnchor();      
    } else {
      //no anchor, so do nothing
    }

Example Sites

Bootstrap 4

This one was particulary intense. It works for both anchors and tabs. In terms of functionality, you can just create an anchor in the CMS as the first item within the main body content of the anchor or tab. Then, the script will find that anchor and open the associated accordion/tab for you on page load.

The code below is from Limestone, because it includes the most recent addition of anchoring to slides.

How To - Scripts

banno-functions.js

Place this code anywhere in your banno-functions.js file.

// Detect anchors, so you can do other things with them
$('a[href*="#"]').each(function() {
  $(this).addClass('anchor');
});

// Functionality for accordions and tabs that are linked to from the menu
banno.site.accordionTabAnchor = function() {
  console.log('inside top of accordiontabanchor function')
  var hash = window.location.hash;
  var anchor = $('a' + hash);

  // Link to Accordion
  if ($('.card.accordion').length > 0) {
    // console.log('there are visible accordions');
    $('.collapse').each(function() {
      if($(this).has(anchor).length) {
        $(this).collapse('show');
        setTimeout(function() { 
          $('html, body').animate({
            scrollTop: $(hash).offset().top - 60 //sticky header space and/or accordion heading
          }, 500);
        }, 500);
      } else {
        // console.log('anchor does not exist in accordion');
      }
    })
  } else {
    // console.log('no accordions on the page');
  }

  // Link to Tab
  if ($('.nav.nav-tabs').length > 0) {
    // console.log('there are visible tabs');
    $('.tab-content .tab-pane').each(function() {
      if($(this).has(anchor).length) {
        var tabID = $(this).attr('aria-labelledby');
        $('.nav.nav-tabs .nav-item .nav-link#' + tabID).tab('show');
        // console.log('tab should be open now');
        setTimeout(function() { 
          $('html, body').animate({
            scrollTop: $(hash).offset().top - 60 //sticky header space and/or accordion heading
          }, 500);
          // console.log('scroll complete');
        }, 500);
      } else {
        // console.log('anchor does not exist in tab pane');
      }
    });
  } else {
    // console.log('no tabs on the page');
  }

  // Link to Slick Slide
  if ($('.slick-slider').length > 0) {
    // console.log('there are visible slides');
    $('.slick-slide').each(function() {
      if($(this).has(anchor).length) {
        setTimeout(function() { 
          $('html, body').animate({
            scrollTop: $(hash).offset().top - 60 //sticky header space and/or accordion heading
          }, 500);
          // console.log('scroll complete');
        }, 500);
        var thisSlideId         = $(this).attr("data-slick-index"),
            thisSlideFullSlider = $(this).parents('.slick-slider');
        // console.log(thisSlideId);
        thisSlideFullSlider[0].slick.slickGoTo(parseInt(thisSlideId));
      } else {
        // console.log('anchor does not exist in slide');
      }
    });
  } else {
    // console.log('no slides on the page');
  }
}

scripts.js

Place this code within the ELSE of the window load function so that it runs only on the published page.

//Open accordion on click of anchor link
if(window.location.hash) {
  banno.site.accordionTabAnchor();      
} else {
  //no anchor, so do nothing
}

Example Sites

Bootstrap 3

It sees if there is an anchor in the URL once the page is loaded, and then finds the closest panel-collapse and opens it, and then scrolls to show the full thing.

How To

The code should be placed in the ELSE statement of the script.js file.

//Open accordion on click of anchor link on a SEPARATE page
if(window.location.hash) {
  var hash = window.location.hash;
  $('a' + hash).closest('.panel-collapse').collapse('show');
  var id = window.location.hash;
  if( id.charAt(1) != "!") {
    if (window.location.hash.length > 0 && $(' ' + id + ' ').length == 1) {
      $('html, body').animate({
        scrollTop: $(id).offset().top - 85 // normally this would be used for sticky header but I'm using it for accordion heading
      }, 500);
    }
  }
} else {
//no anchor, so do nothing
}
//Open accordion on click of anchor link - this section should work if anchor and accordion are on the same page
$('a[data-link-type-id="anchor"]').click(function(e) {
  var anchor = $(this).attr('href').split('#')[1];
  $('#checkingpanels .panel .panel-body a#' + anchor).closest('.panel-collapse').collapse('show');
  $('#checkingpanels .panel .panel-body a#' + anchor).closest('.panel-collapse').parents('.panel').siblings('.panel').children('.panel-collapse').collapse('hide');
});

Example Sites

Bootstrap 2

Example Sites

Tags: bs2, bs3, bs4, bs5 anchor, tab, slide, script, js, jquery, javascript, modal, accordion, scroll, slider, slick