views:

269

answers:

3

I've been writing some jQuery functions that have JavaScript variables and looping, etc inside them - they're becoming long and hard to read. If I want to break them up, how would I do that?

    $(".x").click(function ()
    {
      var i=0;
      for (i=0;i<50;i++)
      {
        if ($("#x"+i).is(':hidden'))
        {
          $("#x"+i).show();
        }
        else
        {
          $("#x"+i).hide();
        }
      }
    });

For example, in the code above, if I want to move the contents of the loop to a separate function and then call that function from inside the loop, what would that need to look like?

+5  A: 

jQuery is javascript, so you can pass functions around just like you would normally do.

// first refactor - separate the function out
$(".x").click(myfunc);

function myfunc() {
{
  var i=0;
  for (i=0;i<50;i++)
  {
    if ($("#x"+i).is(':hidden'))
    {
      $("#x"+i).show();
    }
    else
    {
      $("#x"+i).hide();
    }
  }
}

Although looking at your code it is screaming for all x1 to x50 elements to have the same class applied to it. like so...

<div id='x1' class='xClass'></div>
<div id='x2' class='xClass'></div>
<div id='x3' class='xClass'></div>
.....
<div id='x50' class='xClass'></div>

Then you could do something like

var currentHidden = $('.xClass:hidden')
var currentVisible = $('.xClass:visible')
currentHidden.show();
currentVisible.show();

and yes toggle is even better

$('.xClass').toggle();

then you don't have to loop, which is one of the beauties of using jQuery! =)

Jon Erickson
too bad your answer is inferior to mine.
Jon Erickson
i like how this answer was voted down so much... so haters
Jon Erickson
Mine was as well... The last answer in was the one that was selected as the answer as well. The guy literally sniped the other posted answers and won with something that seems to reinvent the wheel. Why he doesn't just use the "toggle" function is mind blowing...
RSolberg
@RSolberg: I didn't copy anything at all from any other post. If I would have, I wouldn't have answered the actual question, as noone else did that.
Guffa
+4  A: 

The difference between a jQuery function and a JavaScript function is non-existent since jQuery really is javascript.

$(".x").click(DoTheThingYouDo);

function DoTheThingYouDo()
{
  var i=0;
  for (i=0;i<50;i++)
  {
      $("#x"+i).toggle();
  }
}

You can use the toggle() call to show and hide... You could also in theory use a CSS class and just toggle all of the DOM elements that have that class...

$(".x").click(DoTheThingYouDo);

function DoTheThingYouDo()
{
   $(".myclass").toggle();
}
RSolberg
It would be `$(".x").click(DoTheThingYouDo);` (no parentheses after the function name).
musicfreak
I believe the syntax is incorrect. You want: $(".x").click(DoTheThingYouDo). Note: no parentheses. Otherwise you're calling that function and passing the result to the click() handler.
cletus
Thanks @musicfreak and @cletus. Post has been corrected.
RSolberg
+1  A: 

There is no such thing as "JQuery functions", the JQuery code just usually uses an anonymous Javascript function.

To move the contents of the loop into a named function would look like this:

$(".x").click( function() {
  for (var i=0; i<50; i++) toggleItem(i)
});

function toggleItem(i) {
  if ($("#x"+i).is(':hidden')) {
    $("#x"+i).show();
  } else {
    $("#x"+i).hide();
  }
}

However, you could use the cascading properties of CSS to toggle all the items with a simple javascript statement instead of looping through all the elements. Example:

CSS:

<style type="text/css">
.StateOne .InitiallyHidden { display: none; }
.StateTwo .InitiallyVisible { display: none; }
</style>

HTML:

<div class="StateOne" id="StateContainer">
   <div class="InitiallyVisible">Visible first</div>
   <div class="InitiallyHidden">Visible second</div>
   <div class="InitiallyVisible">Visible first</div>
   <div class="InitiallyHidden">Visible second</div>
   <div class="InitiallyVisible">Visible first</div>
   <div class="InitiallyHidden">Visible second</div>
   <div class="InitiallyVisible">Visible first</div>
   <div class="InitiallyHidden">Visible second</div>
</div>

Javascript:

$('.x').click(function() {
   var s = document.getElementById('StateContainer');
   s.className = (s.className == 'StateOne' ? 'StateTwo' : 'StateOne');
});
Guffa
This is great. I really like your alternate approach and I almost understand it too. One question: Did you make a mistake when you defined the styles for StateOne and StateTwo - they are both set to "display:none" - shouldn't StateTwo be visible?
Charlie Kotter
@Charlie: No, it's not a mistake in the styles. The InitiallyHidden class is hidden when the parent element has the class StateOne and visible for StateTwo. The InitiallyVisible class is the opposite. That way you can have one set of elemenets visible for each state.
Guffa
I'm trying this out on my machine but I can't activate the change of state. I put your Javascript inside document ready and then I defined a button: <button class="x">Change StateContainer</button>. But this doesn't change the state. Did I forget to do something? I will edit my question to show you the complete code.
Charlie Kotter
I added the complete HTML above in my question. If you could take a look and maybe point out what I forgot, I would appreciate it. Thanks.
Charlie Kotter
@Charlie: You forgot to include the JQuery library. You need it as you are still using the $ function. You could of course do it without JQuery, then you would put the Javascript code in the button tag instead.
Guffa
The beauty of jQuery is that you do not need to re-invent the wheel. The toggle method will do everything you've coded included the CSS class out of the box! Why write more cord than you absolutely have to?
RSolberg
yes, why create a bunch of CSS classes that are intended to manage the show/hide of an element when jQuery has a built in toggle and filters (:hidden, :visible) that do that all for you?
Jon Erickson
Why? Because it's faster. It makes the page more responsive. You change only one attribute in the document, instead of having JQuery loop through the entire document to look for elements, then loop through the found elements one more time and set an attribute on each one.
Guffa
you're missing the point of even including jQuery on the page. why use jQuery at all then? jQuery selectors are optimized, I don't think you will find ANY performance benefit of using document.GetElementById('StateContainer') over $('#StateContainer')
Jon Erickson
@guffa- can you prove it is faster? I'm totally perplexed by that statement.
RSolberg
@RSolberg: It's easy to prove. Put some elements on a page and toggle them. At 50 elements you start noticing that the JQuery method is slower. At 100 elements the CSS method is still instant while the JQuery method takes upwards a second. At 1000 elements the CSS method has a barely noticable delay while the JQuery method takes over 10 seconds. At 1100 elements the browser stopped the JQuery script because it took too long to execute...
Guffa