2010-04-05 28 views
1

我一直在试图使它成为一个小的jQuery插件,我可以在将来重用,而不必将以下内容写入我的actions.js文件中。如何制作一个自包含的jQuery插件,找到最高的图像高度?

当我使用我的变量tallest设置高度的同一文件中加载时,此方法有效。

var tallest = null; 
$('.slideshow img').each(function(index) { 
    if ($(this).height() >= tallest) { 
    tallest = $(this).height(); 
    } 
}); 
$('.slideshow').height(tallest); 

这个工作,将循环所有的项目,然后将tallest的值设置为找到的最大高度。然而,以下不工作:

(function($){ 
    $.fn.extend({ 
    tallest: function() { 
     var tallest = null; 

     return this.each(function() { 
     if ($(this).height() >= tallest) { 
      tallest = $(this).height(); 
     } 
     }); 
    } 
    }); 
})(jQuery); 

一旦加载我想:

这将是该插件,从它自己的文件加载(包含使用该零件的actions.js文件之前)使用它如下:

$('.slideshow img').tallest(); 
$('.slideshow').height(tallest); 

但是,上述两行返回'最高是未定义'的错误。我该如何做这项工作?任何想法,将不胜感激。关于这个更加的这个完美的使用思考会是如下:

$('.container').height(tallest('.container item')); 

但我甚至不知道从哪里开始得到这个在你传递对象的方式工作,要测量到函数将其添加到函数名称的括号中。

感谢您的阅读,

Jannis

回答

4

你得到“最高的是未定义”的原因是因为tallest只在定义它,不能从外部访问的范围内存在。你需要将所有的逻辑封装在插件中。这里是你会如何做:

(function($) { 
    $.fn.tallest = function(itemsSelector) { 
    return this.each(function() { 
     var $this = $(this), 
     $items = $(itemsSelector, this), 
     tallest = 0; 

     $items.each(function() { 
     var $thisItem = $(this); 
     if ($thisItem.height() > tallest) { 
      tallest = $thisItem.height(); 
     } 
     }); 

     $this.height(tallest); 
    }); 
    }; 
})(jQuery); 

// used like this: 
$('.container').tallest('.item'); 

编辑:

启动带$一个变量名是由Hungarian Notation启发了公约,并用于指示变量包含一个jQuery对象。这不需要以这种方式命名变量,但我觉得它很有用。

我也在这里使用var $this = $(this);来存储一个jQuery对象,它封装了当前正在对其进行操作的DOM对象。这样做的原因是为了提高性能 - 每次需要引用循环中的当前对象时,都可以使用$this,并且不会在内存中创建相同的新对象。在这个例子中,好处不是很清楚,因为$this只能用于一次。通过将当前对象分配给$thisItem,该技术也用于内循环内部。由于该对象在循环中被引用两次,因此可以保存对象实例。

+0

谢谢,这个伟大的工程,我已经学到了很多关于如何建立这些类型的东西!我无法解释的一行是'var $ this = $(this)'这是为了什么目的?另外:为什么你使用'var $ var_name = ...'not'var var_name = ...'它有什么区别?再次感谢。 – Jannis 2010-04-05 08:06:37

+2

我编辑了我的答案来解释这些事情。 :) – 2010-04-05 08:21:05

+0

真棒,感谢您的详细解释。真的很感激它! – Jannis 2010-04-05 09:06:51

4

尝试的你正在尝试这样做更短(更广义的)版本:

$.fn.extend({ 
    max: function(prop) { 
    // create an array of all property values 
    var props = $.map(this, function(i) { return i[prop]; }); 
    // return the result of Math.max() applied to this array 
    return Math.max.apply(Math, props); 
    } 
}); 

使用方法如下:

var tallest = $(".slideshow img").max("height"); 
var widest = $(".slideshow img").max("width"); 

如果你在并行使用多个JavaScript库,你可能要确保$表示插件中的jQuery。通常的方式做,这是包装上面的一个匿名函数,像这样:

(function($) { 
    $.fn.extend({ 
    // ... 
    }); 
)(jQuery); 
+0

这是一个不错的方法,但jQuery的'height'函数覆盖图像的height属性。所以你必须改变属性的检索方式,''我[prop]()','i.attr(prop)'或者this [prop]'或者别的东西。 – Anurag 2010-04-05 08:30:59

+0

@Anurak:这是不合适的,因为'i'永远不会是jQuery对象。它将始终是一个DOM对象。 – Tomalak 2010-04-05 08:33:19

+0

@Tomalak ..你是对的。我有隧道的愿景。 '我'将只是一个DOM对象。 – Anurag 2010-04-05 08:37:56

0
$.fn.tallest = function(outer, margins) { 
    var fn = outer ? "height" : "outerHeight"; 
    return Math.max.apply(Math, $.map(this, function(el) {return $(el)[fn](margins);})); 
};