Skip to main content

Sitecore

Case Study: Lift and Shift from Drupal to Sitecore SXA: Part 3

Abstract Colorful Glow Light Trail With Blue Red Particles Background.

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.

Theme structure

Theme structure

 

 

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.

 

SXA Theme SASS folder

SXA Theme SASS folder

 

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.

Gulp config.js

Gulp config.js

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 Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Maria Xavier

Maria Fernanda Xavier is a Lead Technical Consultant with the Sitecore Optimizely Business Unit. She is a creative Front-end and Sitecore Developer, proficient in various languages. She is constantly seeking to acquire new knowledge and skills in the programming world.

More from this Author

Follow Us