Search code examples
javascriptarchitecturesoftware-design

Extend algorithm that based on loop


my algorithm computes a path through the DOM. It starts with the given component and goes up the tree. Each time a parent component has a specific attribute, the algorithm adds its value to the path.

_computePath(aComponent) {
  let result = '';
  let parent = aComponent.parentNode;

  while (parent.tagName !== 'MY-ROOT-COMPONENT') {
    if (parent.hasAttribute('my-attribute')) {
      result = `/${parent.getAttribute('my-attribute')}${result}`;
    }
    parent = parent.parentNode;
  }

  return result;
}

In an other part of my application, i need a slightly different version.

_computePath(aComponent) {
  let result = '';
  let parent = aComponent.parentNode;

  while (parent.tagName !== 'MY-ROOT-COMPONENT') {
    if (parent.tagName === 'SPECIAL-COMPONENT') {
      result = null;
      break;
    }

    if (parent.condition === 'special') {
      result = null;
      break;
    }

    if (parent.hasAttribute('my-attribute')) {
      result = `/${parent.getAttribute('my-attribute')}${result}`;
    }
    parent = parent.parentNode;
  }

  return result;
}

How can i extend the algorithm of the first loop, without repeat the code?

There is probably a very simple solution, but somehow I can't figure it out.

Thank you


Solution

  • Have the function take a callback that tests for the conditions that cause it to break.

    _computePath(aComponent, stopfun = parent => false) {
      let result = '';
      let parent = aComponent.parentNode;
    
      while (parent.tagName !== 'MY-ROOT-COMPONENT') {
        if (stopfun(parent)) {
          result = null;
          break;
        }
    
        if (parent.hasAttribute('my-attribute')) {
          result = `/${parent.getAttribute('my-attribute')}${result}`;
        }
        parent = parent.parentNode;
      }
    
      return result;
    }
    
    let result1 = obj1._computePath(component1); // no extra stop check
    let result2 = obj2._computePath(component2, parent => parent.tagName === 'SPECIAL-COMPONENT' || parent.condition === 'special');