0

I have a simple function for adding animations to an element: addAnimation(). The main issue I'm having is with the function it calls: updateAnimationProperties(). This function takes up to 4 parameters and at least 3 of them will use the same word, such as:

updateAnimationProperties( name, element, 'animationName', nameStr ); 

the string name is used 3 times. This is how it will be every time this function is called. Another example:

updateAnimationProperties( duration, element, 'animationDuration', durationStr );

duration is repeated 3 times. So I want to make a function that takes the base word: name or duration and automatically concatenates the rest with a string. such as 'animation' + baseVariable or baseVariable + 'Str'.

I've tried using the window method like this:

function updateAnimationProperties( target, element, property ){
  if( target === '' ){
    element.style[ property ] = window[ target + 'Str' ];
  }
  else {
    element.style[ property ] += ', ' + window[ target + 'Str' ];
  }  
}

But it doesn't seem to help. Any idea how I can reduce the number of parameters this function needs by using dynamic variables instead?

Below is the normal code with 4 parameters. I want to reduce these to possibly just 2 parameters.

//\ \ \ \ \ \ \ UPDATE ANIMATION PROPERTIES / / / / / / / / / / / / / / / / / /
function updateAnimationProperties( target, element, property, result ){
  if( target === '' ){
    element.style[ property ] = result;
  }
  else {
    element.style[ property ] += ', ' + result;
  }  
}
/// / / / / / / UPDATE ANIMATION PROPERTIES \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \

//\ \ \ \ \ \ \ \ \ \ ADD ANIMATION / / / / / / / / / / / / / / / / / / / / / /
function addAnimation( element, nameStr, durationStr ){    
  element.classList.add( 'animation' );
    
  var name = element.style.animationName,
      duration = element.style.animationDuration;
    
  updateAnimationProperties( name, element, 'animationName', nameStr ); 
  updateAnimationProperties( duration, element, 'animationDuration', durationStr );
}
/// / / / / / / / / / ADD ANIMATION \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \

var p = document.querySelector( 'p' );

addAnimation( p, 'blur', '100s' );
/* \ \ \ \ \ \ \ \ \ \ \ \ \ ANIMATION DEFINITIONS / / / / / / / / / / / / / */
.animation {
  animation-duration: 1s;
  animation-delay: 0s;
  animation-iteration-count: 1;
  animation-timing-function: ease;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-play-state: running;
}
.blur {
  animation-name: blur;
}

/*\ \ \ \ \ \ \ \ \ \ \ \ \ \ ANIMATION KEYFRAMES / / / / / / / / / / / / / /*/
@keyframes blur {
  100% {
    filter: blur( 5rem );
  }
}
<p>Blur this paragraph</p>
savant
  • 23
  • 6
  • 2
    This is a bad idea. If a variable changes name at any point, everything will break. – Carcigenicate Jun 14 '17 at 23:24
  • It seems like you are seeking a solution to a non-problem. – Scott Marcus Jun 14 '17 at 23:24
  • @ScottMarcus I'm thinking it should make me code more readable. Save space and time. – savant Jun 14 '17 at 23:28
  • @Carcigenicate the base variable is still dynamic so I don't think it should break. – savant Jun 14 '17 at 23:29
  • 1
    @savant I think you're thinking too short term. This may seem like you're saving time, but you'll pay for it during refactoring. I'd also disagree with it making code easier to read, as variables will exist more implicitly, and won't be as obvious to new people reading the code. Don't get caught up in premature optimizations. You may find after all this that you find a better way of going about it entirely; negating the need for problem. – Carcigenicate Jun 14 '17 at 23:39
  • Here's one issue I see. the scope of the **variable** durationStr - is it a global `var`? if not, you've got no chance – Jaromanda X Jun 14 '17 at 23:40
  • @Carcigenicate I admit to be a novice JavaScript programmer but in my mind this seems like an issue that could come up often, no? Right now I'm using a lot of parameters when I think they can be reduced. If there is a better way to use less parameters like restructuring my code what is it? I tried to keep the code simple so it's easy to see. Also thanks for your advice. – savant Jun 14 '17 at 23:41
  • @JaromandaX, generally I try to avoid using global variables but would you recommend it here? – savant Jun 14 '17 at 23:42
  • as you haven't shown the whole context of where you are calling `updateAnimationProperties` it's hard to offer an alternative – Jaromanda X Jun 14 '17 at 23:43
  • no, I would not recommend it here because the only reason you **would** want globals is to achieve this pointless "optimisation" – Jaromanda X Jun 14 '17 at 23:43
  • 1
    The standard way of reducing paremeters (although that's not the sole purpose of creating an object) is identifying which parameters are linked conceptually, creating a single object to represent them, then passing that single object around. An example would be instead of passing a bunch of loose "settings" objects around, you can group them in an object and pass the single Settings object instead. – Carcigenicate Jun 14 '17 at 23:44
  • @Carcigenicate - exactly, that was where I was heading, but without context it's hard to be more specific than what you've just said – Jaromanda X Jun 14 '17 at 23:45
  • @JaromandaX just glossing over my code does it look like to you I'm using an unnecessary amount of parameters? To me it feels so. – savant Jun 14 '17 at 23:45
  • @Carcigenicate that makes sense. Store these values in an object. Thanks I'll see if that helps me clean things up. Btw I'm OCD sorry lol. – savant Jun 14 '17 at 23:46
  • again, @savant, without seeing the code where you **call** those functions, I can't say. – Jaromanda X Jun 14 '17 at 23:46
  • @savant And really, 3 arguments to a function is not that much. It's more than ideal, but certainly not bad. If a function needs 3 pieces of input, that should be explicitly stated using the parameters for the sake of readability. – Carcigenicate Jun 14 '17 at 23:50
  • There really should be a magical way to do this. I'm going to do more research. – savant Jun 14 '17 at 23:53
  • @savant Also note that simply passing an object around isn't the best solution in every case since every function may not need all the data in the object. If you have 3 bits of data that you consistently need everywhere, an object may be a good idea. If you need 1 or 2 bits of the data depending on the function, just creating an object will lead to its own problems. Then you're deconstructing the object all over the place every time you need a single piece of data, which isn't ideal either. This isn't an easy question to answer, but dynamic variables are *rarely* the best solution to any probl – Carcigenicate Jun 14 '17 at 23:56

2 Answers2

1

Your problem is not how to access those variables dynamically, your problem is that you created these many similar variables in the first place. You should remove the target parameter and compute it inside the function, simplifying your code considerably already.

function updateAnimationProperty(element, property, value) {
  var style = element.style;
  property = 'animation' + property.charAt(0).toUpperCase() + property.slice(1);
  if (style[property] === ''){
    style[property] = value;
  } else {
    style[property] += ', ' + value;
  }  
}

function addAnimation(element, name, duration){    
  element.classList.add('animation');
  updateAnimationProperty(element, 'name', name); 
  updateAnimationProperty(element, 'duration', duration);
}

You might also use a structure so that you can iterate the key-value pairs:

function addAnimation(element, name, duration){    
  element.classList.add('animation');
  var props = {name, duration}; // short for {"name": name, "duration": duration}
  for (var p in props)
    updateAnimationProperty(element, p, props[p]);
}

(not that it's really worth here)

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
-2

I found this, hope it works for you. Using the arguments object:

function foo() {
  for (var i = 0; i < arguments.length; i++) {
    alert(arguments[i]);
  }
}

Here the source

Here's the documentation of it from Mozilla: source

===============================================

Or you can use this, the apply function. source 2

Hope that can help.

J.C.
  • 144
  • 1
  • 5