How to make the jQuery toggle function in pure javascript?

Asked

Viewed 2,746 times

5

I found out a little while ago and found very interesting toggle function using functions:

$('body').toggle(
    function(){
        alert('A')
    }, function(){
        alert('B')
    }
);

(In the example I put only 2 functions, I wanted with several)

I tried to do in but I couldn’t (I even looked at the , but there is very complicated).

Explanation:

Since the toggle function will not use DOM elements, it could work by strings:

toggle('D', fn, fn, fn);

so every time D is mentioned in arguments[0] it will perform one function at a time of the array D (D is an array of functions), if it does not exist D it creates a new array with the functions passed to the toggle() and works normally. (In jQuery they do this with date in the elements).

  • Could you specify the goal so that we understand what you really want to do, and what’s your problem? What’s the point of your code?

  • I have an application that does not use jQuery, and there is code function that could very well use this method. It’s been about a week since I’ve been trying to make a hand I can’t, so I’d like the help of someone who understands better...

  • 1

    Do you want to toggle without using jQuery ? ok I’ll edit my answer

  • 2

    Just one piece of information, this function has been removed from jQuery since version 1.9

  • I was trying to look at version 1.7.2 (a lot of people like this version so I always look at it rsrsrs)

  • @Iagobruno I edited my answer including a javascript solution that you can change the order and assign the functions via Array’s facilitating the dynamicity of the code.

  • what would be arguments[0] is actually a URL argument?

  • could be a code to specify which is the array, if it is D, it will execute one function at a time from array D, if it is 'Hr' it will execute one function at a time from 'Hr', if there is no array 'Hr', it creates a new array with the functions passed to toggle

  • 1

    got it! I’ll edit my answer :)

  • @Iagobruno I did as you said, look at my "aryFunctions" as if it were your "D":) but the part of creating an array if there are no functions would not be part of the function, you would have to check if the array is empty or null and create another one, as you want

  • I think that’s good enough for me, check if it’s function, if it’s empty, it’s no problem

Show 6 more comments

2 answers

8


Just keep a circular counter, which picks up the next event from a list each time the element is clicked:

function toggle() {
    var eventos = arguments;
    var contador = -1;
    return function() {
        contador = (contador + 1) % eventos.length;
        eventos[contador].apply(this, arguments);
    };
}

// Exemplo de uso:
document.getElementsByTagName("body")[0].onclick = toggle(
    function() { alert("A"); }, 
    function() { alert("B"); }, 
    ...
);

Example in jsFiddle. It is good to have an alternative implementation, since this method modality .toggle is obsolete (and has been removed in recent versions of jQuery).

Notes:

  1. I chose to increment the counter before to call the function, in case it throws an exception the method does not get "stuck" on a single item...

  2. The suggested implementation is very generic and can be used for other things besides the event onclick. How she passes it on this and arguments for each item in the list, it can be used in place of any function with any signature.


Updating: from what I understood after the question was edited (it’s not clear to me what you want), you want the function to switch between the arguments in the list whenever it is called with the first identical argument, is that it? If it is, I believe there is no alternative but to store your "function map" in a global:

var funcoesToggle = { };
function toggle(qual) {
    if ( !funcoesToggle[qual] )
        funcoesToggle[qual] = { 
            contador: -1,
            funcoes: Array.prototype.slice.call(arguments, 1, arguments.length)
        };

    var escolhido = funcoesToggle[qual];
    escolhido.contador = (escolhido.contador + 1) % escolhido.funcoes.length;
    escolhido.funcoes[escolhido.contador]();
}

// Exemplo de uso:
toggle("D", function() { alert("A"); }, function() { alert("B"); }, function() { alert("C"); }); // A
toggle("D", function() { alert("A"); }, function() { alert("B"); }, function() { alert("C"); }); // B
toggle("Ee", function() { alert("A"); }, function() { alert("B"); }, function() { alert("C"); }); // A
toggle("D", function() { alert("A"); }, function() { alert("B"); }, function() { alert("C"); }); // C
toggle("Ee", function() { alert("A"); }, function() { alert("B"); }, function() { alert("C"); }); // B

Example in jsFiddle. Note that only the first time you use a string is that you need to pass the list of functions, in the following just call with a single argument (although this takes a little the purpose of the function, right?) Anyway, I highly recommend use the original answer code - it is clearer, not "mix responsibilities" (i.e. create a list of functions for "toggle" / use this list of functions).

  • It worked really well! But I won’t use with elements of DOM =p was thinking like this: toggle(’D', fn, fn, fn); so he would perform a see function when’D' was mentioned, or 'Ee' and so on

  • Could you do that? = p

  • @Iagobruno I updated my answer with a clarification regarding the use without elements of the DOM. But I don’t understand what you mean by "when’D' is mentioned". I could edit the question by clarifying what you want to do?

  • I updated the question..

  • That’s what I wanted/ Thank you =D

2

in Jquery would be this:

$('body').toggle(
    function(){
        alert('A')
    }, function(){
        alert('B')
    }, function(){
        alert('C')
    }, function(){
        alert('D')
    }
);

That is, several functions assigned to the body of your document following an execution order.

But you want in pure Javascript, I took advantage and also provided you a choice of order possible, which would be in the case by changing the function parameter toggle() of functions A,B,C, and D you could do whatever order you want, or repeat some function without having to include equal functions again.

That would be the toggle function:

function toggle(aryFunctions,idx){
    document.getElementsByTagName("body")[0].onclick = aryFunctions[idx];
}

And to use we declare an array of functions:

function A(){
  alert('A');
  toggle(aryFunctions,1);
}
function B(){
  alert('B');
  toggle(aryFunctions,2);
}
function C(){
  alert('C');
  toggle(aryFunctions,3);
}
function D(){
  alert('D');
  toggle(aryFunctions,0);
}
var aryFunctions = [A,B,C,D];

document.body.setAttribute("onclick","toggle(aryFunctions,0)");

Thus would execute:

A,B,C,D

It would be the correct circular shape in order, and I’m assigning the click to the tag <body> of your html so not using DOM.

You can change the order dynamically by changing the code of the past functions.

You can also facilitate your job of adding functions dynamically by placing them on aryFunctions which would be an Array making your work much easier in this regard.

See, if I change the array functions to:

function A(){
  alert('A');
  toggle(aryFunctions,3);
}
function B(){
  alert('B');
  toggle(aryFunctions,2);
}
function C(){
  alert('C');
  toggle(aryFunctions,0);
}
function D(){
  alert('D');
  toggle(aryFunctions,1);
}
var aryFunctions = [A,B,C,D];

document.body.setAttribute("onclick","toggle(aryFunctions,0)");

Thus would execute:

A,D,B,C

This way you have enough freedom to do the such toggle() however you prefer.

  • 1

    I am editing my answer to put the solution in pure javascript

  • That’s it! but not wanting to complicate, the code will not use elements of DOM =/ can be through strings...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.