0

So far I'm using different buttons for different transitions (each one with individual function) on one DOM element :

onButtonClickUp = function(){
    document.querySelector('.cube-rot').style.transform="rotateY(90deg)"
    };
onButtonClickDown = function(){
    document.querySelector('.cube-rot').style.transform="rotateY(-90deg)"
};
onButtonClickRight = function(){
    document.querySelector('.cube-rot').style.transform="rotateX(90deg)"
};
onButtonClickLeft = function(){
    document.querySelector('.cube-rot').style.transform="rotateX(-90deg)"
};
document.querySelector('.show-up').addEventListener( 'click', onButtonClickUp, false);
document.querySelector('.show-down').addEventListener( 'click', onButtonClickDown, false);
document.querySelector('.show-left').addEventListener( 'click', onButtonClickLeft, false);
document.querySelector('.show-right').addEventListener( 'click', onButtonClickRight, false);

I'm firing everything off on DomContentLoaded and it's working, but I'd like to combine the functions into one with different cases;


this is what I've tried

 function onButtonClick(rot){
    //rot = rUp || rDown|| rLeft ||rRight ;
    if(rot == 'rUp'){rot = "rotateY(90deg)";}
    else if (rot == 'rDown'){ rot = "rotateY(90deg)"}
    else if (rot == 'rLeft'){ rot = "rotateX(90deg)"}
    else if(rot == 'rRight' ){ rot = "rotateX(-90deg)"};

    cubeRot.style.transform=rot
    };


 document.querySelector('.show-up').addEventListener( 'click', onButtonClick('rUp'), false);
 document.querySelector('.show-down').addEventListener( 'click', onButtonClick('rDown'), false);
 document.querySelector('.show-right').addEventListener( 'click', onButtonClick('rRight'), false);
 document.querySelector('.show-left').addEventListener( 'click', onButtonClick('rLeft'), false);

it doesn't work, adding different EventListners resolves in the last overriding previous.. what's the most convenient way to do this?

4
  • 1
    You can't use onButtonClick('rUp') in addEventListener. This executes the function directly when it's parsed. Change to onButtonClick.bind(null, 'rUp'), Commented Jan 15, 2015 at 17:13
  • cubeRot.style.transform=rot I think cubeRot is not defined, sholdn't it be document.querySelector('.cube-rot').style.transform=rot ? Commented Jan 15, 2015 at 17:15
  • Add some data to your HTML and you can make the function much more generic, e.g. <button class="show-up" data-axis="Y" data-deg="90" /> then you can simply read off this or event.target in the handler Commented Jan 15, 2015 at 17:18
  • @Goten It's defined .... Commented Jan 15, 2015 at 17:18

3 Answers 3

2

Since you are calling onButtonClick() when you do your event binding, it needs to return a function.

function onButtonClick(rot){
    return function(e) {
        //rot = rUp || rDown|| rLeft ||rRight ;
        if(rot == 'rUp'){rot = "rotateY(90deg)";}
        else if (rot == 'rDown'){ rot = "rotateY(-90deg)"}
        else if (rot == 'rLeft'){ rot = "rotateX(90deg)"}
        else if(rot == 'rRight' ){ rot = "rotateX(-90deg)"};

        cubeRot.style.transform=rot;
    };
}

Alternatively, leave the function as is and use .bind():

document.querySelector('.show-up').addEventListener('click', onButtonClick.bind(null, 'rUp'), false);
document.querySelector('.show-down').addEventListener('click', onButtonClick.bind(null, 'rDown'), false);
document.querySelector('.show-right').addEventListener('click', onButtonClick.bind(null, 'rRight'), false);
document.querySelector('.show-left').addEventListener('click', onButtonClick.bind(null, 'rLeft'), false);

The above solutions should get you unblocked. But, there are some more code improvements you could consider.

Instead of that long if .. else if block, you could store the value in an object and look up the value by a key:

var rotations = {
    rUp: "rotateY(90deg)",
    rDown: "rotateY(-90deg)",
    rLeft: "rotateX(90deg)",
    rRight: "rotateX(-90deg)"
};
function onButtonClick(rot) {
    cubeRot.style.transform = rotations[rot];
}

Your event handler has access to the clicked element via this. You don't need to pass a rot argument, you can just look at this.className:

var rotations = {
    up: "rotateY(90deg)",
    down: "rotateY(-90deg)",
    left: "rotateX(90deg)",
    right: "rotateX(-90deg)"
};
function onButtonClick(e) {
    var rot = this.className.slice(5);
    cubeRot.style.transform = rotations[rot];
}
[].slice.call(document.querySelectorAll("[class^='show-']")).forEach(function(el) {
    el.addEventListener("click", onButtonClick, false);
});
Sign up to request clarification or add additional context in comments.

3 Comments

I really like the last solution. It's minimalistic and pure JavaScript.
could you explain why you put that ^ caret to get the selector ?
The caret is part of the attribute starts with selector which takes the form [attributename^='startvalue']. In my code above, it selects all elements whose class attribute starts with 'show-', like 'show-up'. It can be a useful trick, but is a little fragile. For example, the selector would stop working if you added a class to your element so that your attribute became class="button show-up". To then get it to work again, you would have to change your html to class="show-up button".
0

Assuming your buttons are plain HTML buttons with no innerHTML you can do this

<input type="button" action-type="rUp" value="Show up" class="show-up" />

This adds an attribute to the input with the desired action variable.

function onButtonClick(e){
    var rot = e.target.getAttribute("action-type");
    if(rot == 'rUp'){rot = "rotateY(90deg)";}
    else if (rot == 'rDown'){ rot = "rotateY(90deg)"}
    else if (rot == 'rLeft'){ rot = "rotateX(90deg)"}
    else if(rot == 'rRight' ){ rot = "rotateX(-90deg)"};

    cubeRot.style.transform=rot;
    };


 document.querySelector('.show-up').addEventListener( 'click', onButtonClick, false);
 document.querySelector('.show-down').addEventListener( 'click', onButtonClick, false);
 document.querySelector('.show-right').addEventListener( 'click', onButtonClick, false);
 document.querySelector('.show-left').addEventListener( 'click', onButtonClick, false);

When the event is fired e.target refers to the element that fired the event (the button). rot stores the attribute action-type. Based upon rot the correct action will be applied. The advantage is that this doesn't require new functions to be created or functions to be wrapped in a bind.

Comments

0

You can use the this object to reference the button that's triggering the event:

  var onButtonClick = function () {
    var button = this;
    document.querySelector('.dir').innerHTML = button.name;
    switch(button.name) {
       case 'up': alert('up'); break;
       case 'down': alert('down'); break;
       case 'left': alert('left'); break;
       case 'right': alert('right'); break;
     }
  };

  document.querySelector('.show-up').addEventListener('click', onButtonClick, false);
  document.querySelector('.show-down').addEventListener('click', onButtonClick, false);
  document.querySelector('.show-left').addEventListener('click', onButtonClick, false);
  document.querySelector('.show-right').addEventListener('click', onButtonClick, false);

Check this plunk: http://plnkr.co/edit/MJzMffnDZJripzXkiZzc

Happy coding!

Comments

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.