# AJAX Transitions

The template is powered by seamless AJAX transitions thanks to the Barba.js (opens new window) plugin.

WARNING

You need to use a web server to make AJAX transitions work. If you open the template files locally via the filesystem, you may get a browser console error like this one:

"Access to XMLHttpRequest at '...' from origin 
'null' has been blocked by CORS policy:
Cross origin requests are only supported
for protocol schemes: http, data, chrome,
chrome-extension, https."

# Markup

<body>
  <div data-barba="wrapper">
    ...
    <div
      data-barba="container"
      class="js-smooth-scroll"
      id="page-wrapper"
    >
      <main class="page-wrapper__content">
        ...
      </main>
    </div>
    ...
  </div>
</body>
  • Everything outside the Barba container with the data-barba="container" attribute will remain unchanged when navigating the website. This could be a page header and page scripts.
  • To turn off AJAX transitions, remove the data-barba="wrapper" attribute from the div container. Or simply unwrap everything from this container since it doesn't create any styling in the document.

# Excluding Rules

If you don't want specific links to trigger AJAX transitions, here are the options:

Add the data-barba-prevent attribute to the link you want to act as a normal link:

<a
  href="/downloads/somefile.zip"
  data-barba-prevent="self"
>
  Download File
</a>

Add an outer wrapper with the data-barba-prevent="all" attribute for all the links you want to act as normal links:

<div data-barba-prevent="all">
  <a href="/downloads/somefile1.zip">Download File 1</a>
  <a href="/downloads/somefile2.zip">Download File 2</a>
  <a href="/downloads/somefile3.zip">Download File 3</a>
</div>

# Option 3: Add jQuery selectors to the prevent rules

This option is useful if you don't want to change the HTML markup.

<a href="#" class="my-link-class">Link 1</a>
<a href="#" id="my-link-id">Link 2</a>

Find the following template options object in 📄 js/components.js file and specify the custom rules:

...
/**
 * Default Theme Options
 * Used to prevent errors if there is
 * no data provided from backend
 */
if (typeof window.theme === 'undefined') {
  window.theme = {
    ...
    ajax: {
      enabled: true,
      preventRules: '.my-link-class, #my-link-id' // jQuery selectors of the elements to exclude them from AJAX transitions
    },
    ...
  }
}
...

# 3rd-party Scripts Compatibility

When extending the template functionality with a JavaScript plugin that’s not included in the package, you may run into an issue. Your plugin may work well after the initial site load, but when it comes to any AJAX transition, it doesn’t initialize again. This is expected behavior due to the nature of AJAX technology.

All the 3rd-party scripts need to be re-initialized manually each time an AJAX transition occurs. You can do this by placing the initialization code of your plugin inside the initComponents() function wrapper in 📄 js/components.js file:

/**
 * Init Template Components
 * You can init your custom scripts here
 * in this function
 */
function initComponents({
  scope = window.$document,
  container = window.$pageWrapper
}) {
  ...
  // your custom plugins init here
  ...
}

# Ad Trackers Compatibility

Some popular tracking scripts are already AJAX-compatible with the Rhye template. This means you don’t have to write any additional functions to make them work flawlessly. These include:

  • Google Analytics
  • Facebook Pixel
  • Yandex.Metrika

If you need to fine-tune those ad tracking update functions, please take a look at the PJAXUpdateTrackers() function in the js/components.js file:

function PJAXUpdateTrackers() {
  updateGA();
  updateFBPixel();
  updateYaMetrika();

  /**
   * Google Analytics
   */
  function updateGA() {
    if (typeof gtag === 'function' && typeof window.gaData === 'object' && Object.keys(window.gaData)[0] !== 'undefined') {
      const trackingID = Object.keys(window.gaData)[0];
      const pageRelativePath = (window.location.href).replace(window.location.origin, '');

      gtag('js', new Date());
      gtag('config', trackingID, {
        'page_title': document.title,
        'page_path': pageRelativePath
      });
    }
  }

  /**
   * Facebook Pixel
   */
  function updateFBPixel() {
    if (typeof fbq === 'function') {
      fbq('track', 'PageView');
    }
  }

  /**
   * Yandex Metrika
   */
  function updateYaMetrika() {
    if (typeof ym === 'function') {
      const trackingID = getYmTrackingNumber();

      ym(trackingID, 'hit', window.location.href, {
        title: document.title
      });
    }
  }

  function getYmTrackingNumber() {
    if (typeof window.Ya !== 'undefined' && typeof window.Ya.Metrika2) {
      return window.Ya.Metrika2.counters()[0].id || null;
    }

    if (typeof window.Ya !== 'undefined' && typeof window.Ya.Metrika) {
      return window.Ya.Metrika.counters()[0].id || null;
    }

    return null;
  }
}