最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I reduce the redundancies in my jQuery code? - Stack Overflow

programmeradmin3浏览0评论

The size of my JavaScript file is getting out of hand because I have hundreds of links, and each one has its own jQuery function even though they all peform basically the same task.

Here's a short excerpt:

$("#link1").click(function ()
{
  $(".myDiv").hide();
  $("#myDiv1").toggle();
});

$("#link2").click(function ()
{
  $(".myDiv").hide();
  $("#myDiv2").toggle();
});

$("#link3").click(function ()
{
  $(".myDiv").hide();
  $("#myDiv3").toggle();
});

Would there be a way to abstract some of this logic so that I have only a single function instead of hundreds that do the same thing?

The size of my JavaScript file is getting out of hand because I have hundreds of links, and each one has its own jQuery function even though they all peform basically the same task.

Here's a short excerpt:

$("#link1").click(function ()
{
  $(".myDiv").hide();
  $("#myDiv1").toggle();
});

$("#link2").click(function ()
{
  $(".myDiv").hide();
  $("#myDiv2").toggle();
});

$("#link3").click(function ()
{
  $(".myDiv").hide();
  $("#myDiv3").toggle();
});

Would there be a way to abstract some of this logic so that I have only a single function instead of hundreds that do the same thing?

Share Improve this question edited Nov 1, 2010 at 19:37 Peter Mortensen 31.6k22 gold badges109 silver badges133 bronze badges asked Jul 8, 2009 at 19:14 ipso factoipso facto 4472 gold badges7 silver badges11 bronze badges 1
  • Holy FSM. I'm just getting my feet wet with JQuery, and have been working on this exact problem since lunch, and came here to take a Stack Overflow break! – aape Commented Jul 8, 2009 at 19:24
Add a comment  | 

9 Answers 9

Reset to default 12

You can add a class to all the links that do the same thing and act with jQuery on that class.

<a href='whatever' id='link_1' class='toggler'>text</a>
<a href='whatever' id='link_2' class='toggler'>text</a>

jQuery code will be:

$(".toggler").click( function(){
    // toggle the divs
    var number = $(this).attr("id").split('_')[1];
    $(".myDiv").hide();
    $("#myDiv"+ number).toggle();
});

The general approach that I use is to use the traversal methods to find related elements rather than using absolute selectors. This will allow you to apply the same code to elements that are similarly configured without any complicated dependencies on the format of the ids, etc. Done correctly it's also reasonably robust against minor changes to the mark up.

For example, say I have a series of links, each followed by a div that will be toggled by clicking on that link. The links each have a particular class so they can easily be referenced.

<a href="#" class="linkClass">Toggle</a>
<div>
     Some content...
</div>

<a href="#" class="linkClass">Toggle</a>
<div>
     Other content
</div>

I would then find all the links by class, then use the next method to find the associated div and toggle it's visibility. Note that this is a simple example. You may need to use more complicated traversal mechanisms and filter by element type or class, too, depending on your exact mark up.

$('.linkClass').click( function() {
    $(this).next().toggle();
});

What about adding the ID of your target into the href of the link?

<a id="link1" href="#myDiv1" class="toggle">Toggle 1</a><br/>
<a id="link2" href="#myDiv2" class="toggle">Toggle 2</a><br/>
<a id="link3" href="#myDiv3" class="toggle">Toggle 3</a><br/>

Then you could write a single function like so:

$(".toggle").click(function(e) {
    e.preventDefault();
    $(".myDiv").hide();
    $($(this).attr('href')).toggle();
});

Or another approach I've used:

$(".toggle").each(function(i) {
    $(this).click(function(e) {
        e.preventDefault();
        $(".myDiv").hide();
        $(".myDiv:eq("+i+")").toggle();
    });
});

This one is in the same vein as tvanfosson's idea, using some sort of DOM relationship to link the elements, in this case by assuming that the link elements and the div elements are in the same order on the page.

You can just have each click call an external function and pass in a parameter for the number string.

Ex:

$("#link1").click(toggle("1"));
$("#link2").click(toggle("2"));

function toggle(number) {
    $(".myDiv").hide();
    $("#myDiv"+number).toggle();
}
function makeToggler(number) {
    $('#link' + number).click(function() {
        $('.myDiv').hide();
        $('#myDiv' + number).toggle();
    });
}

makeToggler(1);
makeToggler(2);
makeToggler(3);

You can adapt this to meet your naming standards.

Depending on the structure of your divs and links, there are better ways to do it. If you post the structure of your elements, I'll show you one.

I think this is a simple refactoring

you could define a function as such

function doSomethingTo(thisDiv)
{
   $(".myDiv").hide();
   $(thisDiv).toggle();
}

and then just reuse it where you need it

$("#link1).click(doSomethingTo(thisDiv));
$("#link2).click(doSomethingTo(thisDiv));

Building on Craig's solution:

$("#link1, #link2").click(toggle(this));

function toggle(obj) {
    $(".myDiv").hide();
    $("#myDiv" + $(obj).attr("id").replace('link','')).toggle();
}

I change the link become like this (i rename the id to just a number)

<a href='#test1' id='1' class='link'> ... </a>
<a href='#test2' id='2' class='link'> ... </a>
<a href='#test3' id='3' class='link'> ... </a>

and then on js:

$(document).ready(function(){
    $('.link').click(function(){
      $('.myDiv').hide();
      var id = $(this).attr('id'); // take the id
      $('#myDiv'+id).toggle(); 
    });
});

throw your makeToggle into a loop?

function makeToggler(number) {
    $('#link' + number).click(function() {
        $('.myDiv').hide();
        $('#myDiv' + number).toggle();
    });
}

for(i=1;i>=#;i++) {makeToggler(i);}

then you could even have it count your links for you, something link this?:

function countElementsByClass(className){
  var count = 0;
  var o = document.getElementsByTagName("a").className;
  for(var i=0;i<o.length;i+){
      if(o[i].className == "accordion/whatever")
          count ++;
      }

  return count;
}

credit: building on SLaCKS solution

发布评论

评论列表(0)

  1. 暂无评论