Home > Enterprise >  How can I possible shorten this JS code to be more readable?
How can I possible shorten this JS code to be more readable?

Time:12-06

I have the following code:

    ctrl = {
        dataHolder: {
            hide: _ => {
                this.dataHolderTarget.style.display = 'none'
            },
            show: _ => {
                this.dataHolderTarget.style.display = 'block'
            }
        },
        dataBtnHolder: {
            hide: _ => {
                this.dataBtnHolderTarget.style.display = 'none'
            },
            show: _ => {
                this.dataBtnHolderTarget.style.display = 'block'
            }
        },
        playerOneBtn: {
            hide: _ => {
                this.playerOneBtnTarget.style.display = 'none'
            },
            show: _ => {
                this.playerOneBtnTarget.style.display = 'block'
            },
            load: res=>{
                this.dataset.res=res
            }
        },
        playerTwoBtn: {
            hide: _ => {
                this.playerTwoBtnTarget.style.display = 'none'
            },
            show: _ => {
                this.playerTwoBtnTarget.style.display = 'block'
            },
            load: res=>{
                this.dataset.res=res
            }
        }
    }

How can I make so I don't repeat those code blocks? As I'm aware of DRY, this code looks somehow ugly. As you can see hide and show are everywhere. The last 2 elements have load functions.

CodePudding user response:

You can refactor the repeated hide/show code to a separate function.

Then, you can refactor creating a {hide: ..., show: ...} object for a given element into a separate function:

function toggleVisibility(element, displayValue) {
  element.style.display = displayValue;
}

function makeHideShow(target) {
  return {
    hide: () => toggleVisibility(target, "none"),
    show: () => toggleVisibility(target, "block"),
  };
}

ctrl = {
  dataHolder: makeHideShow(this.dataHolderTarget),
  dataBtnHolder: makeHideShow(this.dataBtnHolderTarget),
  playerOneBtn: {
    ...makeHideShow(this.playerOneBtnTarget),
    load: (res) => this.dataset.res = res,
  },
  playerTwoBtn: {
    ...makeHideShow(this.playerTwoBtnTarget),
    load: (res) => this.dataset.res = res,
  },
};

CodePudding user response:

This is a demonstration of the extreme lengths you can go to to not repeat yourself...

Note: in this code, although the console.log() output will contain e and b in the functions, those should be correctly bound to the appropriate values:

const ctrl = Object.fromEntries(
  ['dataHolder','dataBtnHolder','playerOneBtn','playerTwoBtn'].map(i=>[i, {
    ...Object.fromEntries([['hide','none'],['show','block']].map(([a,b])=>
      [a,(e=>(_=>this[e].style.display = b))(`${i}Target`)])),
    ...i.startsWith('player')?{load: res=>this.dataset.res=res}:{}
  }
]))

console.log(ctrl)

CodePudding user response:

const elements = ['dataHolderTarget', 'dataBtnHolderTarget', 'playerOneBtnTarget', 'playerTwoBtnTarget'];

const ctrl = {};

elements.forEach(element => {
  ctrl[element] = {
    hide: _ => this[element].style.display = "none",
    show: _ => this[element].style.display = "block"
  };
});

// Add the `load` property to the `playerOneBtn` and `playerTwoBtn` objects.
ctrl.playerOneBtnTarget.load = res => (this.dataset.res = res);
ctrl.playerTwoBtnTarget.load = res => (this.dataset.res = res);

In this way, you can avoid repeating yourself when defining the object properties, and you can easily add new elements to the object by simply adding them to the elements array. Additionally, you can easily add new properties to all of the elements by adding them to the object that is created in the forEach loop.

  • Related