开发者

More efficient switch statement in jQuery/JavaScript

I'm working on an app that uses a switch statement to provide custom animations depending on which link has been clicked to trigger the animation. It seems like a lot of code to get what I want, but I'm having a little trouble figuring out a better way to do it.

What happens is that when you click on a link, a div will open up to reveal hidden content and the other divs will slide to the side of the screen. Kinda like a custom accordian.

My switch statement looks like this - the history paramater is taken from the id of the clicked link. The divs are stored in an object called rpsObject.

switch( history ) {
    case "biography" :
        $("#" + rpsObject.boxId[1]).myAnimation();
        $("#" + rpsObject.boxId[2]).myAnimation({ top : 80 });
        $("#" + rpsObject.boxId[3]).myAnimation({ top: 160 });
        $("#" + rpsObject.boxId[4]).myAnimation({ top: 240 });
        $("#" + rpsObject.boxId[5]).fadeInCloseLink();
    break;
    case "blog" :
        $("#" + rpsObject.boxId[0]).myAnimation();
        $("#" + rpsObject.boxId[2]).myAnimation({ top : 80 });
        $("#" + rpsObject.boxId[3]).myAnimation({ top: 160 });
        $("#" + rpsObject.boxId[4]).myAnimation({ top: 240 });
        $("#" + rpsObject.boxId[5]).fadeInCloseLink();
    break;
    case "diary" :
        $("#" + rpsObject.boxId[0]).myAnimation();
        $("#" + rpsObject.boxId[1]).myAnimation({ top : 80 });
        $("#" + rpsObject.boxId[3]).myAnimation({ top: 160 });
        $("#" + rpsObject.boxId[4]).myAnimation({ top: 240 });
        $("#" + rpsObject.boxId[5]).fadeInCloseLink();
    break;
    case "reviews" :
        $("#" + rpsObject.boxId[0]).myAnimation();
        $("#" + rpsObject.boxId[1]).myAnimation({ top : 80 });
        $("#" + rpsObject.boxId[2]).myAnimation({ top: 160 });
        $("#" + rpsObject.boxId[4]).myAnimation({ top: 240 });
        $("#" + rpsObject.boxId[5]).fadeInCloseLink();
    break;
    case "images" :
        $("#" + rpsObject.boxId[0]).myAnimation();
        $("#" + rpsObject.boxId[1]).myAnimation({ top : 80 });
        $("#" + rpsObject.boxId[2]).myAnimation({ top: 160 });
        $("#" + rpsObject.boxId[3]).myAnimation({ top: 240 });
        $("#" + rpsObject.boxId[5]).fadeInCloseLink();
    break;
    case "contact" :
        $("#" + rpsObject.boxId[0]).myAnimation();
        $("#" + rpsObject.boxId[1]).myAnimation({ top : 80 });
        $("#" + rpsObject.boxId[2]).myAnimation({ top: 160 });
        $("#" + rpsObject.boxId[3]).myAnimation({ top: 240 });
        $("#" + rpsObject.boxId[4]).fadeInCloseLink();
    break;
}

Hopefully it should be pretty obvious what I'm doing here!

The functions myAnimation() and fadeinCloseLink() are custom functi开发者_开发百科ons. The latter must be performed on the last item of the object, which on complete trigger a custom animation for the selected div. The function fadeinCloseLink() does the following:

$.fn.fadeInCloseLink = function() {
    $(this).animate({ "left" : "640px", "top" : "320px", "height" : "80px" }, 300,
    function(){
        disFull.animate({ "opacity" : "toggle", "height" : "toggle" }, 500);
    });
}

Where disFull refers to the div that will be affected.

Hopefully this is clear enough to get my question across.


Here is what I came up with quickly

var historyItems = "biography,blog,diary,reviews,images,contact".split(",")
var currentSettings = [];
for (var i=0;i< historyItems.length; i++) {
  if (historyItems[i] != history) currentSettings.push(i)
}  
$("#" + rpsObject.boxId[currentSettings[0]]).myAnimation();
$("#" + rpsObject.boxId[currentSettings[1]]).myAnimation({ top : 80 });
$("#" + rpsObject.boxId[currentSettings[2]]).myAnimation({ top: 160 });
$("#" + rpsObject.boxId[currentSettings[3]]).myAnimation({ top: 240 });
$("#" + rpsObject.boxId[currentSettings[4]]).fadeInCloseLink();


You could refactor your code so that all the repeated portions go into a single function.

var myFunction = function(indexes){
        $("#" + rpsObject.boxId[indexes[0]]).myAnimation();
        $("#" + rpsObject.boxId[indexes[1]]).myAnimation({ top : 80 });
        $("#" + rpsObject.boxId[indexes[2]]).myAnimation({ top: 160 });
        $("#" + rpsObject.boxId[indexes[3]]).myAnimation({ top: 240 });
        $("#" + rpsObject.boxId[indexes[4]]).fadeInCloseLink();
    }

    switch( history ) {
    case "biography" :
       myFunction([1,2,3,4,5]);
    break;
    case "blog" :
        myFunction([0,2,3,4,5]);
    break;
    case "diary" :
        myFunction([0,1,3,4,5]);
    break;
    case "reviews" :
        myFunction([0,1,2,4,5]);
    break;
    case "images" :
        myFunction([0,1,2,3,5]);
    break;
    case "contact" :
        myFunction([0,1,2,3,4]);
    break;
    }


If I'm seeing it correctly, each case features this sequence of calls:

.myAnimation();
.myAnimation({ top : 80 });
.myAnimation({ top: 160 });
.myAnimation({ top: 240 });
.fadeInCloseLink();

...and it's just which elements those are called on that varies. So that's our first opportunity for refactoring.

The second is probably that we can do a lookup table:

var elementMap = {
    "biography": [1, 2, 3, 4, 5],
    "blog":      [0, 2, 3, 4, 5],
    "diary":     [0, 1, 3, 4, 5],
    "reviews":   [0, 1, 2, 4, 5],
    "images":    [0, 1, 2, 3, 5],
    "contract":  [0, 1, 2, 3, 4]
};

and so:

var elements = elementMap[history];
rpsObject.boxId[elements[0]].myAnimation();
rpsObject.boxId[elements[1]].myAnimation({ top : 80 });
rpsObject.boxId[elements[2]].myAnimation({ top: 160 });
rpsObject.boxId[elements[3]].myAnimation({ top: 240 });
rpsObject.boxId[elements[4]].fadeInCloseLink();

Now, whether that's more maintainable is another question, but with your broader knowledge of the overall project, you may well be able to apply the techniques in a way which is both concise and maintainable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜