Оборачивая каждый элемент, вы можете сохранить оболочку в массиве, а затем обработать массив, а не пересматривать 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% случаев это не имеет значения.Если вы имеете дело с лотом элементов, это так.