6

I have a simple contributed module that I have written. It has pretty basic javascript. I decided to clean it up and write it in vanilla js, removing jQuery since that seems to be the direction we're going. Here is the resulting code...

const viewSourceLinks = document.querySelectorAll(
  '.simple-styleguide--view-sourecode'
);

[].forEach.call(viewSourceLinks, el => {
  el.addEventListener('click', () => {
    el.nextElementSibling.classList.toggle('active');
  });
});

const calculableElements = document.querySelectorAll('.calculate');

[].forEach.call(calculableElements, el => {
  const measuredElement = el.querySelector('.measure');
  const info = el.querySelector('.info');
  const lineHeight = `<label>line-height:</label> ${
    window.getComputedStyle(measuredElement).lineHeight
  }`;
  const fontSize = `<label>font-size:</label> ${
    window.getComputedStyle(measuredElement).fontSize
  }`;
  const margins = `<label>margin:</label> ${
    window.getComputedStyle(measuredElement).marginBottom
  }
        ${window.getComputedStyle(measuredElement).marginRight} ${
    window.getComputedStyle(measuredElement).marginBottom
  } ${window.getComputedStyle(measuredElement).marginLeft}`;

  info.innerHTML = `${fontSize}<br/>${lineHeight}<br/>${margins}`;
});

My question is, is this ok? Is this good enough to include as is? In general, it seems the advice is to always add your javascript within attached behaviors.

However, once I go down that road, I'm pretty much having to include jQuery in the wrapper. And I would much rather just have vanilla javascript.

The resulting code with behaviors ends up being something like this...

(($, Drupal) => {
  Drupal.behaviors.simpleStyleguide = {
    attach(context) {

      const viewSourceLinks = context.querySelectorAll(
        '.simple-styleguide--view-sourecode'
      );

      [].forEach.call(viewSourceLinks, el => {
        el.addEventListener('click', () => {
          el.nextElementSibling.classList.toggle('active');
        });
      });

      const calculableElements = context.querySelectorAll('.calculate');

      [].forEach.call(calculableElements, el => {
        const measuredElement = el.querySelector('.measure');
        const info = el.querySelector('.info');
        const lineHeight = `<label>line-height:</label> ${
          window.getComputedStyle(measuredElement).lineHeight
        }`;
        const fontSize = `<label>font-size:</label> ${
          window.getComputedStyle(measuredElement).fontSize
        }`;
        const margins = `<label>margin:</label> ${
          window.getComputedStyle(measuredElement).marginBottom
        }
              ${window.getComputedStyle(measuredElement).marginRight} ${
          window.getComputedStyle(measuredElement).marginBottom
        } ${window.getComputedStyle(measuredElement).marginLeft}`;

        info.innerHTML = `${fontSize}<br/>${lineHeight}<br/>${margins}`;
      });

    },
  };
})(jQuery, Drupal);

I've also read that if you have BigPipe enabled, you have to include jQuery. Not sure if that's true or not.

The vanilla js code above seems to be working. I just want to know that I'm doing this right, and that I'm not violating some Drupal standard by not wrapping it in a behavior.

Note: I should mention there is no ajax behavior in this module. If there were, perhaps I would have to use behaviors and context.

8

The best practice is still to use Drupal's behaviors system even when not relying on jQuery. See Drupal 8 Drupal.behaviors without jquery for reference.

That said, I think you're on the right path. I find jQuery just slows down the page load when vanilla JS will usually do the trick. That's just my opinion and there's a lot of debate out there.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.