DEV Community

Bukunmi Odugbesan
Bukunmi Odugbesan

Posted on

Coding Challenge Practice - Question 27

The task is to implement a DOM Wrapper to support method chaining. The wrapper only needs to have css(propertyName: string, value: any).

The boilerplate code

function $(el) {
  // your code here
}
Enter fullscreen mode Exit fullscreen mode

The DOM wrapper needs to be flexible i.e it should handle several ways of identifying elements. If a string is passed to the css(), it should be treated as a CSS selector. If a NodeList (like the result of document.querySelectorAll) or an array of elements is passed, those are converted to a normal array. If a single HTML element is passed, it is wrapped in an array.

if(typeof el === 'string') {
    elements = Array.from(document.querySelectorAll(el));
  } else if(el instanceof NodeList || Array.isArray(el)) {
    elements.from(el)
  } else if(el instanceof HTMLElement) {
    elements = [el]
  } 
Enter fullscreen mode Exit fullscreen mode

Css property names are usually written in kebab case, while in Javascript's DOM API, they must be camelCase. To handle both forms, a helper function that converts kebab case to camel case is included

function toCamelCase(prop) {
    return prop.replace(/-([a-z])/g, (_, ch) => ch.toUpperCase())
  }
Enter fullscreen mode Exit fullscreen mode

The css method accepts two arguments, a property name and a value. It loops through all the elements in the wrapper, setting each element to its corresponding value, converting to camel case where necessary. Every method in the wrapper returns the same api object at the end of its execution. This allows another method to be immediatelly called on the same line

 const api = {
    css(propertyName, value) {
      if(typeof propertyName === 'undefined') return api;
      const jsProp = toCamelCase(propertyName);
      elements.forEach(elm => {
        if(elm || elm.style) {
          elm.style[jsProp] = value;
        }
      });
      return api;
    }
   }
Enter fullscreen mode Exit fullscreen mode

The final code is:

function $(el) {
  // your code here
  let elements = [];

  if(typeof el === 'string') {
    elements = Array.from(document.querySelectorAll(el));
  } else if(el instanceof NodeList || Array.isArray(el)) {
    elements.from(el)
  } else if(el instanceof HTMLElement) {
    elements = [el]
  } 

  function toCamelCase(prop) {
    return prop.replace(/-([a-z])/g, (_, ch) => ch.toUpperCase())
  }

  const api = {
    css(propertyName, value) {
      if(typeof propertyName === 'undefined') return api;
      const jsProp = toCamelCase(propertyName);
      elements.forEach(elm => {
        if(elm || elm.style) {
          elm.style[jsProp] = value;
        }
      });
      return api;
    }
    }
  return api;
}
Enter fullscreen mode Exit fullscreen mode

That's all folks!

Top comments (0)