Welcome to case study on doing a lift and shift from Drupal to Sitecore 10.2 and SXA. In this article, we’ll talk about converting the CSS and Drupal-specific JavaScript.
Let’s start with SXA Theme regarding CSS/SCSS and JS files. Here is a quick recap from the previous article for this series. We used the SXA theme, and deleted all the SCSS, CSS, JS and image files that came with the new theme by default. We maintained most of the SXA theme folders’ structure, and we also introduced other folders from client’s Drupal theme/styles to make the theme somewhat familiar to them. Moreover, we used the standard creative exchange process to upload the files into Sitecore.
Styles
In this next section we will focus on CSS/SCSS development. This was a lift and shift project, therefore we transferred over client’s code and kept some folders/files naming the same from Drupal site.
As illustrated above, we introduced folders like blocks, components, and pages which are not part of SXA OOTB Theme. When you add a new folder at that directory level you will need to update the gulp config.js so files inside those folders get transpiled/compiled.
Scripts
Let’s talk about scripts. The Drupal site was using jQuery, so we kept the same JavaScript library. We created new JS files since we were customizing SXA components or using the OOTB SXA components. We also cloned code from Drupal site, but we had to clean up the syntax and make sure we were using the Sitecore SXA theming script syntax.
Drupal site jQuery component
/**
* @file
* Scripts for ‘Product gallery block’.
* Depends from Slick slider library.
*/
(function ($, Drupal) {
‘use strict’;
Drupal.behaviors.accordion = {
attach: function (context, settings) {
// Run simple accordion
if ($(‘.accordion-block’).length) {
Drupal.behaviors.accordion.initAccordion();
}
},
/**
* simpleAccordion
*
* @param {any} settings
*/
initAccordion: function(settings) {
// Check settings
var set = settings || {};
//Check only by height
var isFullyVisible = function (element) {
if (element instanceof $) {
element = element[0];
}
var rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight)
);
};
// If settings has opened pane index
if (set.hasOwnProperty(‘opened’)) {
$(‘.accordion-block’).find(‘.accordion-block__content’).get(set.opened).classList.add(‘accordion-block__content–is-opened’);
$(‘.accordion-block’).find(‘.accordion-block__toggler’).get(set.opened).classList.add(‘accordion-block__toggler–is-active’);
}
// Add even listener to the labels
$(‘.accordion-block’).find(‘.accordion-block__toggler’).once(‘accordionClick’).click(function () {
var self = $(this),
accordionToggles = $(‘.accordion-block’).find(‘.accordion-block__toggler’),
labelActiveClass = ‘accordion-block__toggler–is-active’,
expanded = self.hasClass(labelActiveClass) ? ‘false’ : ‘true’;
self.toggleClass(labelActiveClass).attr(‘aria-expanded’, expanded);
accordionToggles.each(function (index, element) {
if (element !== self[0]) {
$(element).removeClass(labelActiveClass).attr(‘aria-expanded’, ‘false’);
}
});
//Expand or collapse this panel
self
.parent()
.next()
.slideToggle(‘fast’, function () {
// Scroll back to the pane header if it’s not in the viewport.
if (!isFullyVisible(self)) {
$(‘html, body’).stop().animate(
{
scrollTop: self.offset().top,
},
300
);
}
});
//Hide the other panels
$(‘.accordion-block__content’)
.not(self.parent().next())
.slideUp(‘fast’);
$(‘.accordion-block__view-all’).toggleClass(
‘accordion-block__view-all–is-opened’
);
// Attach analytic.
var btnState = self.hasClass(‘accordion-block__toggler–is-active’)
? ‘Opened’
: ‘Closed’,
btnText = self[0].innerText.trim();
Drupal.behaviors.accordion.analytics.userInteractsWithAccordion(
btnState,
btnText
);
});
$(‘.accordion-block’).find(‘.accordion-block__view-all’).once(‘accordionViewAll’).click(function () {
$(‘.accordion-block__content’).toggleClass(‘accordion-block__content–view-all’);
});
},
analytics: {
userInteractsWithAccordion: function(state, btnText) {
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: ‘pnaAccordionEngaged’,
eventCategory: ‘Accordion’,
eventAction: ‘Accordion ‘ + state,
eventLabel: ‘Accordion Label: ‘ + btnText,
eventValue: undefined,
eventOrigin: ‘front-end’,
eventVars: {
accordionInteraction: state,
accordionLabel: btnText,
}
});
}
}
}
}(jQuery, Drupal));
Sitecore SXA jQuery component
XA.component.accordion = (function ($) {
const api = {
init: function () {
if ($(‘.accordion-block’).length) {
api.initializeaccordion();
}
},
initializeaccordion: function () {
$(‘.accordion-block’).find(‘.accordion-block__toggler’).click(function (e) {
e.stopImmediatePropagation();
let self = $(this),
accordionToggles = $(‘.accordion-block’).find(‘.accordion-block__toggler’),
labelActiveClass = ‘accordion-block__toggler–is-active’,
expanded = self.hasClass(labelActiveClass) ? ‘false’ : ‘true’;
self.toggleClass(labelActiveClass).attr(‘aria-expanded’, expanded);
accordionToggles.each(function (index, element) {
if (element !== self[0]) {
$(element).removeClass(labelActiveClass).attr(‘aria-expanded’, ‘false’);
}
});
//Expand or collapse this panel
self
.parent()
.next()
.slideToggle(‘fast’, function () {
// Scroll back to the pane header if it’s not in the viewport.
if (!api.isFullyVisible(self)) {
$(‘html, body’).stop().animate(
{
scrollTop: self.offset().top,
},
300
);
}
});
//Hide the other panels
$(‘.accordion-block__content’)
.not(self.parent().next())
.slideUp(‘fast’);
$(‘.accordion-block__view-all’).toggleClass(
‘accordion-block__view-all–is-opened’
);
});
$(‘.accordion-block’).find(‘.accordion-block__view-all’).click(function () {
$(‘.accordion-block__content’).toggleClass(‘accordion-block__content–view-all’);
});
// remove repeat resource title
var seen = {};
$(‘.resources-list__title’).each(function() {
var txt = $(this).text();
if (seen[txt]){
$(this).remove();
}
else{
seen[txt] = true;
}
});
},
isFullyVisible: function (element) {
if (element instanceof $) {
element = element[0];
}
let rect = element.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight)
);
}
}
return api;
})(jQuery);
XA.register(‘accordion’, XA.component.accordion);
From a lift and shift point of view, the process worked as we expected! We faced a few issues due to copying over SCSS, JS and live HTML. One of them was dealing with CSS classes that were dynamically added via JS into the markup for specific scenarios. Also, SCSS files missing due to third party plugins. However, with the help of our QA team we caught these scenarios in time to fixed them all.
With all that in place, we delivered the new Sitecore site with the same look as their old Drupal site. We saved a lot of time and bugs by importing their styles and scripts.
Leave A Comment