Refactoring an app organised into 'config', 'methods', and 'actions'

55 Views Asked by At

I made the following example app which changes the position of a label depending on the blur or focus state of a text input.

// Config
const $label = document.getElementById("label");
const $input = $("#input");
const initCoords = { y: 62, x: 10 };
const animationDuration = 0.2;
const ease = Power1.easeOut;
const labelFontSizes = {
  blur: 40,
  focus: 30
};

// Methods
const initLabelPosition = () => TweenLite.set($label, { ...initCoords });

const moveLabelAboveInput = () =>
  TweenLite.to($label, animationDuration, {
    y: 0,
    x: 0,
    fontSize: labelFontSizes.focus,
    ease
  });

const moveLabelInsideInput = () =>
  TweenLite.to($label, animationDuration, {
    ...initCoords,
    fontSize: labelFontSizes.blur,
    ease
  });

const changeOutlineColor = () => {
  TweenLite.to($input, animationDuration, {
    css: { outlineColor: "green" }
  });
};

// Actions
initLabelPosition();

$input.focus(function() {
  moveLabelAboveInput();
  changeOutlineColor();
});

$input.blur(function() {
  if (!$input.val()) {
    moveLabelInsideInput();
  }
});
body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: 'Slabo 27px', serif;
  background-color: snow;
}

#label {
  display: block;
  font-size: 40px;
  color: grey;
  pointer-events: none;
}

#input {
  font-size: 50px;
  padding: 10px;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
  <label id="label" for="input">Username</label>
  <input id="input" type="text">
</div>

My questions are:

  • How can I refactor code like this so that all my variables are not sitting in the global namespace?

  • Is there a best practice for code organised in such a way?

  • One idea I have is to refactor this into a class, in which all the config variables are attached to the class instance of this, and all the methods are class methods. Then the actions would come separately to the class. Would this be considered an appropriate or optimised solution?

1

There are 1 best solutions below

0
On

I didn't want my comment go unnoticed so here is a practical implementation of CSS only input box animation the way you wanted. I believe code optimization starts from using the readily available tools in the first place, like CSS3.

However you may of course have other reasons to beef up your code with JS, to allow dynamical changes, easy portability, whatnot...; that's another story.

So here we refactor your JS code to nonexistence.

body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: 'Slabo 27px', serif;
  background-color: snow;
}

#input-container {
  position: relative;
  width: 33vw;
  font-size: 3vmin;
}

#label {
  position: absolute;
  top: 0;
  left: 0;
  padding: 0.5em;
  width: 100%;
  font-size: 3em;
  color: grey;
  pointer-events: none;
  box-sizing: border-box;
  transition: top 0.2s, font-size 0.2s;
}

#input {
  padding: 0.5em;
  width: 100%;
  font-family: inherit; /* required due to FF bug */
  font-size: 3em;
  box-sizing: border-box;
}

#input:focus + #label,
#input:valid + #label {
  top: -2em;
  font-size: 2em;
}

#input:focus,
#input:valid {
  outline-color: green;
  outline-style: solid; /* required for FF */
  outline-width: 1px;   /* required for FF to match Chrome default*/
}
<div id="input-container">
  <input id="input" type="text" required>
  <label id="label" for="input">Username</label>
</div>