3

大家好,

我编写了一个脚本,使用<figure>和从常规图像标签创建 HTML5 图像标题<figcaption>

我的 CMS 使用 FCKEditor,它总是将嵌入的图像放置在段落中。所以我的脚本围绕图像构建了一个<figcaption>,然后将其移到段落之外(参见html5,段落内的图/图标题给出了不可预测的输出))。

我编写的脚本有效,但它遍历了 DOM 两次,因为我想不出一种只遍历 DOM 一次的方法。如果更精通 JQuery 的人可以就如何简化/改进脚本提供一些建议,我将不胜感激。

谢谢,-NorthK

// use like this: 
// <img class="caption" src="http://placehold.it/350x150" alt="Sample image caption" />
//
$(document).ready(function() {
// iterate over each element with img.caption
$('img.caption').each(function() {
    var classList = $(this).attr('class');  // grab the image's list of classes, if any
    $(this).wrap('<figure class="' + classList + '"></figure>'); // wrap the <img> with <figure> and add the saved classes
    $(this).after('<figcaption>' + $(this).attr('alt') + '</figcaption>'); // add the caption
    $(this).removeAttr('class'); // remove the classes from the original <img> element
});

// now iterate over each figure.caption we built, and relocate it to before its closest preceding paragraph
$('figure.caption').each(function() {
    $(this).parent('p').before($(this));
});
})
4

2 回答 2

5

在包装每个元素时,可以将包装器保存在数组中,然后处理数组而不是重新遍历 DOM:

$(document).ready(function() {
    var wrappers = [];

    // iterate over each element with img.caption
    $('img.caption').each(function() {
        var $this = $(this);
        var classList = this.className;  // grab the image's list of classes, if any
        $this.wrap('<figure class="' + classList + '"></figure>'); // wrap the <img> with <figure> and add the saved classes

        // Remember the wrapper here:
        wrappers.add($this.parent());

        $this.after('<figcaption>' + $(this).attr('alt') + '</figcaption>'); // add the caption
        $this.removeAttr('class'); // remove the classes from the original <img> element
    });

    // now iterate over each figure.caption we built, and relocate it to before its closest preceding paragraph
    $.each(wrappers, function(index, item) {
        $(item).parent('p').before(item);
    });

    // And if you're done with it, release it:
    wrappers = null;
});

这是一个简化的示例:

HTML:

<p><img class='caption' src='http://www.gravatar.com/avatar/6d8ebb117e8d83d74ea95fbdd0f87e13?s=48&d=identicon&r=PG'></p>
<p><img class='caption' src='http://www.gravatar.com/avatar/ca3e484c121268e4c8302616b2395eb9?s=48&d=identicon&r=PG'</p>

JavaScript:

jQuery(function($) {

  var wrappers = [];
  $("img.caption").each(function() {
    var $this = $(this);
    $this.wrap("<figure class='" + this.className + "'>");
    wrappers.push($this.parent('figure'));
  });
  $.each(wrappers, function(index, item) {
    $(item).addClass("foo");
  });
  wrappers = null;
});

实时复制


题外话:您似乎对效率感兴趣,所以我会提到:每次调用都$(this)需要多次函数调用和内存分配。与其重复执行,不如在每个循环中执行一次并缓存结果。我在上面做了一个例子。从性能的角度来看,不断地编写$(this)同一个函数并不理想,尽管在 99% 的情况下,这并不重要。如果你要处理很多元素,它确实如此。

于 2011-03-25T22:47:02.613 回答
0

您可以使用该方法在第一次迭代中unwrap摆脱。<p>您还可以使用链接来简化语法。

$('.caption').each(function() {
    $(this)
        .unwrap() // ditch the conflicting pararaph parent wrapper
        .wrap('<figure class="' + $(this).attr('class') + '" />') // wrap the figure tag instead, jQuery can handle a self closing tag
        .after('<figcaption>' + $(this).attr('alt') + '</figcaption>') // add the caption
        .removeAttr('class'); // remove the classes from the original <img> element
});

http://jsfiddle.net/pxfunc/AGgL2/

于 2011-03-25T22:45:15.870 回答