# AJAX Transitions
The template is powered by smooth AJAX transitions thanks to the Barba.js (opens new window) plugin. Here is the correct markup for all the template pages:
<body>
<div data-barba="wrapper">
...
<div class="page-wrapper" data-barba="container">
<main class="page-wrapper__content">
...
</main>
</div>
...
</div>
</body>
Everything outside the Barba container [data-barba="container"] will remain unchanged from page to page. This could be the page header and page scripts.
To turn off AJAX transitions, simply remove the attribute [data-barba="wrapper"] from the div container. Or simply unwrap everything from this container since it doesn't create any styling in the document.
<body>
...
</body>
WARNING
You need to use a web server to make AJAX transitions work. If you open the template files locally, 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."
# Typography Transitions
Cassio has an exclusive text AJAX transition between pages. The heading a visitor clicks on will smoothly fly and land on the next page, giving that seamless motion experience.
When a user clicks on a link, the script checks if the heading inside the link is eligible for the text flying transition.
<a class="figure-portfolio figure-portfolio-big text-right" href="project-6.html" data-pjax-link="flyingHeading">
...
<div class="figure-portfolio-big__content">
<h4 class="figure-portfolio-big__heading split-text js-text-to-fly js-split-text" data-split-text-type="lines, words, chars" data-split-text-set="chars">Loft Apartment</h4>
</div>
</a>
There are a few conditions for the correct transition:
- The link should have
[data-pjax-link="flyingHeading"]set. - The heading inside the link should have the
.js-text-to-flyclass. - The actual heading should be split into chars so those can fly independently.
- The text in the current and next headings should be the same. That way, the script will have the correct amount of chars for calculation.
The next page should also be prepared accordingly:
<section class="section section-masthead section-masthead_big-heading section-fullheight text-center bg-white" data-os-animation="data-os-animation">
<div class="section-fullheight__inner">
<h1 class="js-text-to-fly split-text js-split-text section-masthead__heading section-masthead__heading-big text-xxl" data-split-text-type="lines, words, chars" data-split-text-set="chars">Projects 001</h1>
</div>
</section>
So the page which is being loaded should also have the heading split into chars with js-text-to-fly.
TIP
The rest of the attributes and visual styling can be whatever you need. For example, you can have different colors, font sizes, margins, etc. The transition will work even if you have a 2-row heading on the current page and a 1-row heading on the next page!
# Excluding Rules
If you don't want specific links to trigger the AJAX transitions, here are the options.
# Option 1. Excluding the individual link
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>
# Option 2. Excluding all the nested links
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 object in the js/components.js file and specify your own AJAX preventing rules in the excludeRules array:
var PJAX = function () {
var $barbaWrapper = $('[data-barba="wrapper"]');
if (!$barbaWrapper.length) {
return;
}
barba.init({
timeout: 6000,
// don't trigger barba for links outside wrapper
prevent: ({ el }) => {
var $el = $(el),
excludeRules = [
/* Custom Rules */
'.my-link-class',
'#my-link-id',
//////////////////
'[data-elementor-open-lightbox]', // Elementor lightbox gallery
'.lang-switcher a' // Polylang & WPML language switcher
];
// elementor preview
if (typeof elementor === 'object') {
return true;
}
// clicked on elementor outside barba wrapper
if ($el.closest($barbaWrapper).length < 1) {
return true;
}
// custom rules from WordPress Customizer
if (window.theme.customPreventRules) {
excludeRules.push(window.theme.customPreventRules);
}
// check against array of rules to prevent
return $el.is(excludeRules.join(','));
},
// custom transitions
transitions: [
PJAXTransitionGeneral,
PJAXTransitionFlyingHeading,
PJAXTransitionOverlayMenu,
]
});
}
# 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 the HTML/js/components.js file:
function initComponents($scope = window.$document) {
window.PageHeader = new Header();
if (typeof window.PageMenu === 'undefined') {
window.PageMenu = new MenuOverlay();
}
new SectionMasthead($scope);
new SectionPortfolio($scope);
new SectionNavProjects($scope);
new SectionFullscreenSlider($scope);
new SectionContent($scope);
new SectionAbout($scope);
new SectionServices($scope);
new SectionTestimonials($scope);
new SectionAwards($scope);
new SliderImages($scope);
new SliderProjects($scope);
new SliderLetters($scope);
$('.js-video').magnificPopup();
new ScrollDown();
new Form();
new GMap($scope);
new ButtonCircle($scope);
new Grid();
fixMobileBarHeight();
lazyLoad($scope);
$('[data-art-parallax]').artParallax({
ScrollMagicController: window.SMController,
SmoothScrollController: window.SB
});
// your custom plugin init here
}
The initComponents() function is called each time a new page is loaded (normal or AJAX way).
# Ad Trackers Compatibility
Some of the popular tracking scripts are already AJAX-compatible with the Cassio template. It means that 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 HTML/js/components.js file.
function PJAXUpdateTrackers() {
updateGA();
updateFBPixel();
updateYaMetrika();
/**
* Google Analytics
*/
function updateGA() {
if (typeof gtag === 'function') {
if (window.gaData !== 'undefined' && Object.keys(window.gaData)[0] !== 'undefined') {
var trackingID = Object.keys(window.gaData)[0],
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') {
var 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;
}
}
}