0

I Need to refactor an IIFE in ES6. In ES6 let and const have a block scope, so I really need an IIFE in ES6? This is the ES5 version of the code:

var oojs = (function(oojs) {
  var createToolbarItems = function(itemElements) {
    var items = [];
    [].forEach.call(itemElements,
      function(el, index, array) {

        var item = {
          toggleActiveState: function() {
            this.activated = !this.activated;
          }
        };

        Object.defineProperties(item, {
          el: {
            value: el
          },
          enabled: {
            get: function() {
              return !this.el.classList.contains('disabled');
            },
            set: function(value) {
              if (value) {
                this.el.classList.remove('disabled');
              } else {
                this.el.classList.add('disabled');
              }
            }
          },
          activated: {
            get: function() {
              return this.el.classList.contains('active');
            },
            set: function(value) {
              if (value) {
                this.el.classList.add('active');
              } else {
                this.el.classList.remove('active');
              }
            }
          }
        });

        items.push(item);
      });
    return items;
  };

  oojs.createToolbar = function(elementId) {
    var element = document.getElementById(elementId);
    var items = element.querySelectorAll('.toolbar-item');

    return {
      items: createToolbarItems(items)
    }
  };

  return oojs;
}(oojs || {}));

What is the best way to translate this code in ES6? I tried many solution but I miss something, and I get an error: oojs is not defined.

Maybe I can use a Class instead? As you can see from the code I'm writing a Toolbar API in a OOP way (I think...)

Thanks for any help

EDIT: Thanks to georg, I try to refactor my code using classes. This is the new ES6 version:

class Toolbar {
  constructor(elementId) {
    this.elementId = elementId;
  }
  get items() {
    const element = document.getElementById(this.elementId);
    return element.querySelectorAll(".toolbar-item");
  }
  createToolbarItems() {
    return [...this.items].map(el => new ToolbarItem(el));
  }
}

class ToolbarItem {
  constructor(el) {
    this.el = el;
  }
  get enabled() {
    return !this.el.classList.contains('disabled');
  }
  set enabled(value) {
    if (value) {
      this.el.classList.remove('disabled');
    } else {
      this.el.classList.add('disabled');
    }
  }
  get activated() {
    return this.el.classList.contains('active');
  }
  set activated(value) {
    if (value) {
      this.el.classList.add('active');
    } else {
      this.el.classList.remove('active');
    }
  }
  toggleActiveState() {
    this.activated = !this.activated;
  }
}

// const toolbar = new Toolbar('myToolbar');
// const toolbarItems = toolbar.createToolbarItems();

EDIT: please check if is the right way to write this code, I'm pretty new to ES6

Thanks again

7
  • "I can use a Class instead" - sure, Toolbar and ToolbarItem are close candidates. Commented Feb 27, 2018 at 14:27
  • @georg can you help me with the syntax? Commented Feb 27, 2018 at 14:28
  • "I get an error: oojs is not defined": When I run your snippet, there is no such error. Commented Feb 27, 2018 at 14:29
  • @mplungjan “How can I turn this ES5 code into its ES6 equivalent?” is a specific question about a programing problem (SO realm). Definitely off-topic for code review as the code is not implemented as expected. Commented Feb 27, 2018 at 14:31
  • @trincot: the error appears when I use (improperly) ES6 Commented Feb 27, 2018 at 14:31

1 Answer 1

3

You can start by factoring out the toolbar item code (var item and below):

class ToolbarItem 
{
    constructor(element) {
      ....
    }
}

Now, decide if you want to keep enabled and activated as properties or refactor them to explicit methods like isEnabled and setEnabled. In the former case it would be,

class ToolbarItem {
   get enabled() {
      ...
   }
   set enabled(value) {
      ...
   }
}

while ordinary methods can be defined like this:

class ToolbarItem {
   isEnabled() {
      ...
   }
   setEnabled(value) {
      ...
   }
}

Once you get this sorted out, replace your item initialization code with items.push(new ToolbarItem(el)) and test.

Hope this helps you getting started, good luck!

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, I'll post a refactoring in first answer EDIT.
@ufollettu: in your code createToolbarItems could be simply [... itemElements].map(el => new ToolbarItem(el)). Get used to arrow functions, they're amazing!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.