简体   繁体   English

DRY-如何合并这些jQuery函数?

[英]DRY - How Can I Combine These jQuery Functions?

ORIGINAL QUESTION: 原始问题:

I'm looking at this ENORMOUS block of code that I KNOW can be slimmed by about 90%. 我正在看这个我知道可以减少90%左右的代码块。 I just can't figure out how to do it. 我只是不知道该怎么做。

Here's the block I'm referring to: 这是我指的块:

$('table.model a').click(function(){
var divForm = [$('div.form')];
$(this).closest('div').not('.close').fadeOut(500).animate({"top": "-414px"}, 100).fadeIn('fast');
    if ($(this).hasClass('tmi48')) {
        $('img.i4').show();
        $('h1.tmi48').show();
    } else if ($(this).hasClass('tmi416')) {
        $('img.i4').show();
        $('h1.tmi416').show();
    } else if ($(this).hasClass('tmi432')) {
        $('img.i4').show();
        $('h1.tmi432').show();
    } else if ($(this).hasClass('tmi464')) {
        $('img.i4').show();
        $('h1.tmi464').show();
    } else if ($(this).hasClass('tmi4s16')) {
        $('img.i4s').show();
        $('h1.tmi4s16').show();
    } else if ($(this).hasClass('tmi4s32')) {
        $('img.i4s').show();
        $('h1.tmi4s32').show();
    } else if ($(this).hasClass('tmi4s64')) {
        $('img.i4s').show();
        $('h1.tmi4s64').show();
    } else if ($(this).hasClass('tmi516')) {
        $('img.i5').show();
        $('h1.tmi516').show();
    } else if ($(this).hasClass('tmi532')) {
        $('img.i5').show();
        $('h1.tmi532').show();
    } else if ($(this).hasClass('tmi564')) {
        $('img.i5').show();
        $('h1.tmi564').show();
    } else if ($(this).hasClass('tmi5c16')) {
        $('img.i5c').show();
        $('h1.tmi5c16').show();
    } else if ($(this).hasClass('tmi5c32')) {
        $('img.i5c').show();
        $('h1.tmi5c32').show();
    } else if ($(this).hasClass('tmi5c64')) {
        $('img.i5c').show();
        $('h1.tmi5c64').show();
    } else if ($(this).hasClass('tmi5s16')) {
        $('img.i5s').show();
        $('h1.tmi5s16').show();
    } else if ($(this).hasClass('tmi5s32')) {
        $('img.i5s').show();
        $('h1.tmi5s32').show();
    } else if ($(this).hasClass('tmi5s64')) {
        $('img.i5s').show();
        $('h1.tmi5s64').show();
    } else if ($(this).hasClass('atti48')) {
        $('img.i4').show();
        $('h1.atti48').show();
    } else if ($(this).hasClass('atti416')) {
        $('img.i4').show();
        $('h1.atti416').show();
    } else if ($(this).hasClass('atti432')) {
        $('img.i4').show();
        $('h1.atti432').show();
    } else if ($(this).hasClass('atti464')) {
        $('img.i4').show();
        $('h1.atti464').show();
    } else if ($(this).hasClass('atti4s16')) {
        $('img.i4s').show();
        $('h1.atti4s16').show();
    } else if ($(this).hasClass('atti4s32')) {
        $('img.i4s').show();
        $('h1.atti4s32').show();
    } else if ($(this).hasClass('atti4s64')) {
        $('img.i4s').show();
        $('h1.atti4s64').show();
    } else if ($(this).hasClass('atti516')) {
        $('img.i5').show();
        $('h1.atti516').show();
    } else if ($(this).hasClass('atti532')) {
        $('img.i5').show();
        $('h1.atti532').show();
    } else if ($(this).hasClass('atti564')) {
        $('img.i5').show();
        $('h1.atti564').show();
    } else if ($(this).hasClass('atti5c16')) {
        $('img.i5c').show();
        $('h1.atti5c16').show();
    } else if ($(this).hasClass('atti5c32')) {
        $('img.i5c').show();
        $('h1.atti5c32').show();
    } else if ($(this).hasClass('atti5c64')) {
        $('img.i5c').show();
        $('h1.atti5c64').show();
    } else if ($(this).hasClass('atti5s16')) {
        $('img.i5s').show();
        $('h1.atti5s16').show();
    } else if ($(this).hasClass('atti5s32')) {
        $('img.i5s').show();
        $('h1.atti5s32').show();
    } else if ($(this).hasClass('atti5s64')) {
        $('img.i5s').show();
        $('h1.atti5s64').show();
    } else if ($(this).hasClass('vzi48')) {
        $('img.i4').show();
        $('h1.vzi48').show();
    } else if ($(this).hasClass('vzi416')) {
        $('img.i4').show();
        $('h1.vzi416').show();
    } else if ($(this).hasClass('vzi432')) {
        $('img.i4').show();
        $('h1.vzi432').show();
    } else if ($(this).hasClass('vzi464')) {
        $('img.i4').show();
        $('h1.vzi464').show();
    } else if ($(this).hasClass('vzi4s16')) {
        $('img.i4s').show();
        $('h1.vzi4s16').show();
    } else if ($(this).hasClass('vzi4s32')) {
        $('img.i4s').show();
        $('h1.vzi4s32').show();
    } else if ($(this).hasClass('vzi4s64')) {
        $('img.i4s').show();
        $('h1.vzi4s64').show();
    } else if ($(this).hasClass('vzi516')) {
        $('img.i5').show();
        $('h1.vzi516').show();
    } else if ($(this).hasClass('vzi532')) {
        $('img.i5').show();
        $('h1.vzi532').show();
    } else if ($(this).hasClass('vzi564')) {
        $('img.i5').show();
        $('h1.vzi564').show();
    } else if ($(this).hasClass('vzi5c16')) {
        $('img.i5c').show();
        $('h1.vzi5c16').show();
    } else if ($(this).hasClass('vzi5c32')) {
        $('img.i5c').show();
        $('h1.vzi5c32').show();
    } else if ($(this).hasClass('vzi5c64')) {
        $('img.i5c').show();
        $('h1.vzi5c64').show();
    } else if ($(this).hasClass('vzi5s16')) {
        $('img.i5s').show();
        $('h1.vzi5s16').show();
    } else if ($(this).hasClass('vzi5s32')) {
        $('img.i5s').show();
        $('h1.vzi5s32').show();
    } else if ($(this).hasClass('vzi5s64')) {
        $('img.i5s').show();
        $('h1.vzi5s64').show();
    } else if ($(this).hasClass('uli48')) {
        $('img.i4').show();
        $('h1.uli48').show();
    } else if ($(this).hasClass('uli416')) {
        $('img.i4').show();
        $('h1.uli416').show();
    } else if ($(this).hasClass('uli432')) {
        $('img.i4').show();
        $('h1.uli432').show();
    } else if ($(this).hasClass('uli464')) {
        $('img.i4').show();
        $('h1.uli464').show();
    } else if ($(this).hasClass('uli4s16')) {
        $('img.i4s').show();
        $('h1.uli4s16').show();
    } else if ($(this).hasClass('uli4s32')) {
        $('img.i4s').show();
        $('h1.uli4s32').show();
    } else if ($(this).hasClass('uli4s64')) {
        $('img.i4s').show();
        $('h1.uli4s64').show();
    } else {
        return;
    }
    divForm[0].animate({"top": "+=557px"}, 500, function(){
        $(this).animate({"top": "-=20px"}, 200);
    }); 
});

Here's the jsFiddle: http://jsfiddle.net/6YUuT/ 这是jsFiddle: http : //jsfiddle.net/6YUuT/

As you can see, each link is calling the same form, but the header and image change based on which link was clicked.I've tried playing around with shared classes, but I just can't come up with a fix that works. 如您所见,每个链接都调用相同的表单,但是标题和图像会根据所单击的链接而改变。我尝试使用共享类,但是我无法提供一个有效的修复程序。

REVISIONS & NEW QUESTION: 修订和新问题:

I've ALMOST got all the functions worked out properly, but I ran into my original problem, this time in a different spot. 我已经使ALMOST的所有功能正常工作,但是这次我遇到了最初的问题,这次是在另一个地方。 I've got another enormous code block that needs to go away and though it seems almost identical to the last one, it's different enough that I haven't been able to come up with a solution that works. 我还有另一个巨大的代码块需要删除,尽管它看起来与上一个代码块几乎相同,但又有足够的不同之处,以至于我无法提出一种可行的解决方案。

Here's the jsFiddle: http://jsfiddle.net/9Pr8L/ 这是jsFiddle: http : //jsfiddle.net/9Pr8L/

And the offending/offensive code block: 以及令人反感的代码块:

function linkHide() {
    //var r = /(?:^| )((?:tm|att|vz|sp|ul)(app?|bb?|htc?|lg?|mot?|sam?))(?: |$)/;
    if ($('span.tm').is(':visible') && $('span.app').is(':visible')) {
        $('td.tmapp').show();
    } 
    if ($('span.tm').is(':visible') && $('span.bb').is(':visible')) {
        $('td.tmbb').show();
    }
    if ($('span.tm').is(':visible') && $('span.htc').is(':visible')) {
        $('td.tmhtc').show();
    }
    if ($('span.tm').is(':visible') && $('span.lg').is(':visible')) {
        $('td.tmlg').show();
    }
    if ($('span.tm').is(':visible') && $('span.mot').is(':visible')) {
        $('td.tmmot').show();
    }
    if ($('span.tm').is(':visible') && $('span.sam').is(':visible')) {
        $('td.tmsam').show();
    }
    if ($('span.att').is(':visible') && $('span.app').is(':visible')) {
        $('td.attapp').show();
    }
    if ($('span.att').is(':visible') && $('span.bb').is(':visible')) {
        $('td.attbb').show();
    }
    if ($('span.att').is(':visible') && $('span.htc').is(':visible')) {
        $('td.atthtc').show();
    }
    if ($('span.att').is(':visible') && $('span.lg').is(':visible')) {
        $('td.attlg').show();
    }
    if ($('span.att').is(':visible') && $('span.mot').is(':visible')) {
        $('td.attmot').show();
    }
    if ($('span.att').is(':visible') && $('span.sam').is(':visible')) {
        $('td.attsam').show();
    }
    if ($('span.vz').is(':visible') && $('span.app').is(':visible')) {
        $('td.vzapp').show();
    }
    if ($('span.vz').is(':visible') && $('span.bb').is(':visible')) {
        $('td.vzbb').show();
    }
    if ($('span.vz').is(':visible') && $('span.htc').is(':visible')) {
        $('td.vzhtc').show();
    }
    if ($('span.vz').is(':visible') && $('span.lg').is(':visible')) {
        $('td.vzlg').show();
    }
    if ($('span.vz').is(':visible') && $('span.mot').is(':visible')) {
        $('td.vzmot').show();
    }
    if ($('span.vz').is(':visible') && $('span.sam').is(':visible')) {
        $('td.vzsam').show();
    }
    if ($('span.ul').is(':visible') && $('span.app').is(':visible')) {
        $('td.ulapp').show();
    }
    if ($('span.ul').is(':visible') && $('span.bb').is(':visible')) {
        $('td.ulbb').show();
    }
    if ($('span.ul').is(':visible') && $('span.htc').is(':visible')) {
        $('td.ulhtc').show();
    }
    if ($('span.ul').is(':visible') && $('span.lg').is(':visible')) {
        $('td.ullg').show();
    }
    if ($('span.ul').is(':visible') && $('span.mot').is(':visible')) {
        $('td.ulmot').show();
    }
    if ($('span.ul').is(':visible') && $('span.sam').is(':visible')) {
        $('td.ulsam').show();
    }
};

I've now slimmed down the HTML so that ALL the table data exists in ONE table with variable headers, images and links. 现在,我精简了HTML,使所有表数据都存在于具有可变标题,图像和链接的ONE表中。 I was able to edit wared's regex so that it returns the proper strings, but I could not think of a way to actually USE it. 我能够编辑wared的正则表达式,以便它返回正确的字符串,但是我想不出一种实际使用它的方法。

I assume that there can be only one of these classes per anchor. 我假设每个锚点只能有这些类之一。 In this case, a regular expression allows you to extract this class from the class attribute, and extract the image class from it at the same time ( this refers to the anchor element) : 在这种情况下,可以使用正则表达式从class属性中提取此类,并同时从中提取图像类( this是指anchor元素):

var r = /(?:^| )((?:tm|att|vz|ul)(i\d[a-z]?)\d\d?)(?: |$)/;
var m = $(this).attr('class').match(r);
if (m) {
    $('img.' + m[2]).show();
    $('h1.' + m[1]).show();
} else {
    return;
}

The regular expression : 正则表达式:

(?:^| )            the beginning of the string or a whitespace
(...)              capture -> group 1 : the heading class
(?:tm|att|vz|ul)   any of these prefixes, one time
(...)              capture -> group 2 : the image class
i\d[a-z]?          "i" + one digit + any letter, zero or one times
\d\d?              one or two digits
(?: |$)            a whitespace or the end of the string

To summarize : 总结一下:

"tm" or "att" or "vz" or "ul"
+ "i" + one digit + zero or one letter (group 2, example : "i4s")
+ one or two digits

This will match strings like tmi416 , atti4s16 or vzi48 . 这将匹配tmi416atti4s16vzi48类的字符串。 To make things a bit more clear, you can open your browser console and paste the following code into it : 为了使事情更加清楚,您可以打开浏览器控制台并将以下代码粘贴到其中:

'foo atti4s16 bar'.match(
    /(?:^| )((?:tm|att|vz|ul)(i\d[a-z]?)\d\d?)(?: |$)/
)

You can see that an array is returned containing both the heading class (index 1 = group 1) and the image class (index 2 = group 2) : 您可以看到返回的数组既包含标题类(索引1 =组1)又包含图像类(索引2 =组2):

[" atti4s16 ", "atti4s16", "i4s"]

Now that your question is completely different, here's further optimization that again puts most of the data into data structure and then avoids duplicated code by just looping over the data structure: 现在您的问题完全不同了,下面是进一步的优化,它再次将大多数数据放入数据结构中,然后仅通过遍历数据结构来避免重复代码:

function linkHide() {

    var atts = ["tm", "att", "vz", "ul"];
    var mfrs = ["app", "bb", "htc", "lg", "mot", "sam"];

    for (var i = 0; i < atts.length; i++) {
        if ($("span." + atts[i]).is(':visible')) {
            for (var j = 0; j < mfrs.length; j++) {
                if ($("span." + mfrs[j]).is(':visible')) {
                    $("td" + "." + atts[i] + mfrs[j]).show();
                }
            }                
        }
    } 
};

This was the answer to an original question which has now been completed changed/edited to something different: 这是对原始问题的答案,该问题现已完成更改/编辑为不同的内容:

You can put all the classes in an array and walk through the array to condense it down to this: 您可以将所有类放入数组中,并遍历该数组以将其压缩为:

$('table.model a').click(function(){
    var classList = ['tmi416', 'tmi432', ... put other classes here];
    var divForm = [$('div.form')];
    var self = $(this);
    self.closest('div').not('.close').fadeOut(500).animate({"top": "-414px"}, 100).fadeIn('fast');
    for (var i = 0; i < classList.length; i++) {
        if (self.hasClass(classList[i])) {
            // figure out class name to show
            // algorithm is to remove chars before first "i" and 
                    //    then remove trailing 16,32 or 64
            var name = classList[i].replace(/^.*?i/, "i").replace(/16$|32$|64$/,"");
            $(".img." + name).show();
            $("h1." + classList[i]).show();
            break;
        }
    }
    divForm[0].animate({"top": "+=557px"}, 500, function(){
        $(this).animate({"top": "-=20px"}, 200);
    }); 
});

Or, if you put a common prefix of "xxx-" on the target classnames, you can do it like this without having to build the long list of class names ahead of time: 或者,如果在目标类名上添加通用前缀"xxx-" ,则可以这样做,而不必提前构建长类名列表:

$('table.model a').click(function(){
    var divForm = [$('div.form')];
    var self = $(this);
    self.closest('div').not('.close').fadeOut(500).animate({"top": "-414px"}, 100).fadeIn('fast');
    var classes = " " + this.className + " ";
    var match = classes.match(/\sxxx-([^ ]+)(i[^ ]+)(\d\d)\s/);
    if (match) {
        $(".img." + match[1] + match[2]).show();
        $("h1." + match[1] + match[2] + match[3]).show();
    }
    divForm[0].animate({"top": "+=557px"}, 500, function(){
        $(this).animate({"top": "-=20px"}, 200);
    }); 
});

If we saw the actual HTML and understood the overall problem, you can probably simplify this much more by changing how you organize your HTML or what classes you use or by putting custom attributes on some elements. 如果我们看到了实际的HTML并理解了整个问题,则可以通过更改组织HTML的方式或使用的类或在某些元素上添加自定义属性来进一步简化此操作。 But, that requires us seeing much more of what you're doing than just rewriting the one block of code. 但是,这不仅需要重写一小段代码,还需要我们看到您正在做的事情。

Create a map of objects to classes: 创建对象到类的映射:

IE: IE浏览器:

var map = {
  "uli48": {
          img: "i4",
          h1: "uli48"
        }
}

then you can loop along the lines of 然后您可以沿着

var cls, classList = $(this).attr("class").split(" ");

for(var i=0; i<classList.length; i++) {
   cls = classList[i];
   if(map[cls]) {
      $("h1"+cls.h1).show();
      $("img"+cls.img).show();
    }
}

Let's assume the mentioned classes are exclusive. 让我们假设所提到的类是排他的。 If you depend on the order of the if statements, you'll need some more tweaks. 如果您依赖于if语句的顺序,则需要进行一些其他调整。

First, build the dictionary of class of this and the associated classes: 首先,构建this和相关类的字典:

var relatedImgs = { "tmi48" : "i4", ... };

This can be done with sed or an editor macro from your code. 可以使用sed或代码中的编辑器宏来完成。 Then, you need to find out classes of this : 然后,您需要找出this

var thisClasses = $(this).attr('class').split(' ');

Then just try to find the class which is in the relatedImgs dictionary and use the related information: 然后,只需尝试找到relatedImgs词典中的类并使用相关信息即可:

function findRelated(element) {
    var thisClasses = $(element).attr('class').split(' ');
    for (var i in thisClasses) {
        var imgClass = relatedImgs[thisClasses[i]];
        if (imgClass) {
            return [$("h1." + thisClasses[i]), 
                    $("img." + imgClass)];
        }
    }
    return null;
}

var related = findRelated(this);
if (related !== null) {
    for (var i in related) {
        related.show();
    }
}

This answer is an extension of the following one : https://stackoverflow.com/a/20926579/1636522 . 该答案是以下内容的扩展: https : //stackoverflow.com/a/20926579/1636522

So, in order to prevent the regular expression from growing more and more as your needs evolve (in other words, to keep things readable and maintainable), you could split it into smaller regular expressions, each one matching a specific device category. 因此,为了防止正则表达式随着需求的增长而越来越多(换句话说,是为了保持可读性和可维护性),可以将其拆分为较小的正则表达式,每个正则表达式都与特定的设备类别匹配。 This results in something close to the class list solution , but the list is reduced to a few patterns : 使得结果与类列表解决方案很相似,但是列表简化为以下几种模式:

var patterns = [
    '(i\\d[a-z]?)\\d\\d?', // iPhone
    '(sgs\\d)',            // Samsung Galaxy S
    '(bbz\\d\\d?)'         // Blackberry Z
];

var i = -1;
while (++i < patterns.length) {
    patterns[i] = new RegExp(
        '(?:^| )((?:tm|att|vz|ul)' + patterns[i] + ')(?: |$)'
    );
}

You could also feed the list manually : 您也可以手动输入列表:

var patterns = [
    /(?:^| )((?:tm|att|vz|ul)(i\d[a-z]?)\d\d?)(?: |$)/,
    /(?:^| )((?:tm|att|vz|ul)(sgs\d))(?: |$)/,
    /(?:^| )((?:tm|att|vz|ul)(bbz\d\d?))(?: |$)/
];

Initialize the click event as follows : 初始化click事件,如下所示:

$('a').click(function () {
    var cls = $(this).attr('class'),
        i = -1, 
        m;
    while (++i < patterns.length) {
        if (m = cls.match(patterns[i])) {
            $('img.' + m[2]).show();
            $('h1.' + m[1]).show();
            break;
        }
    }
});

Here is a demo : http://jsfiddle.net/wared/UTe5F/ . 这是一个演示: http : //jsfiddle.net/wared/UTe5F/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM