JQuery .each () в обратном направлении

433

Я использую JQuery для выбора некоторых элементов на странице, а затем перемещаю их в DOM. Проблема, с которой я сталкиваюсь, - это выбрать все элементы в обратном порядке, которые JQuery естественно захочет выбрать. Например:

<ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
</ul>

Я хочу выбрать все элементы li и использовать для них команду .each(), но я хочу начать с пункта 5, затем пункта 4 и т.д. Возможно ли это?

Теги:
arrays
reverse

12 ответов

592
Лучший ответ
$($("li").get().reverse()).each(function() { /* ... */ });
  • 2
    Это не работает с моей стороны, вероятно, потому что обратная функция не определена.
  • 25
    Array.reverse существует с версии JavaScript 1.1. Какой браузер вы используете?
Показать ещё 5 комментариев
387

Я представляю вам самый чистый способ когда-либо, в виде самого маленького плагина jquery:

jQuery.fn.reverse = [].reverse;

Использование:

$('jquery-selectors-go-here').reverse().each(function () {
    //business as usual goes here
});

-Все кредит Майкла Гири в его сообщении здесь: http://www.mail-archive.com/[email protected]/msg04261.html

  • 0
    Хорошо, я согласен, что это круто, но почему это работает? Вы копируете (свободно говоря) Array.prototype.reverse в jQuery.prototype.reverse, и при его вызове this объект имеет числовые свойства и свойство длины, поэтому javascript может индексировать его и применять функцию массива к экземпляру jQuery. ?
  • 5
    Важно отметить, что индекс не перевернут, поэтому, если вы хотите сделать, например, только последние три, вы не можете ожидать, что <li>Item 5</li> будет иметь индекс 0.
Показать ещё 6 комментариев
57

Вы можете сделать

jQuery.fn.reverse = function() {
    return this.pushStack(this.get().reverse(), arguments);
}; 

за которым следует

$(selector).reverse().each(...) 
  • 12
    Этот подход был первоначально предложен Джоном Резигом (разработчик jQuery) в списке рассылки jQuery .
17

Вот несколько вариантов для этого:

Первый: без jQuery:

var lis = document.querySelectorAll('ul > li');
var contents = [].map.call(lis, function (li) {
    return li.innerHTML;
}).reverse().forEach(function (content, i) {
    lis[i].innerHTML = content;
});

Демо здесь

... и с jQuery:

Вы можете использовать это:

$($("ul > li").get().reverse()).each(function (i) {
    $(this).text( 'Item ' + (++i));
});

Демо здесь

Другой способ, используя также jQuery с reverse:

$.fn.reverse = [].reverse;
$("ul > li").reverse().each(function (i) {
    $(this).text( 'Item ' + (++i));
});

Эта демонстрация здесь.

Еще одна альтернатива - использовать length (количество элементов, соответствующих этому селектору), и спуститься туда, используя index каждой итерации. Затем вы можете использовать это:

var $li = $("ul > li");
$li.each(function (i) {
    $(this).text( 'Item ' + ($li.length - i));
});

Эта демонстрация здесь

Еще один, относящийся к приведенному выше:

var $li = $("ul > li");
$li.text(function (i) {
    return 'Item ' + ($li.length - i);
});

Демо здесь

13

Я предпочитаю создание обратного подключаемого модуля, например

jQuery.fn.reverse = function(fn) {       
   var i = this.length;

   while(i--) {
       fn.call(this[i], i, this[i])
   }
};

Использование, например:

$('#product-panel > div').reverse(function(i, e) {
    alert(i);
    alert(e);
});
  • 0
    Мне тоже нравится эта идея / код, но она не возвращает цепочечный объект (который перевернут), как ответы с более высоким рейтингом :) Тем не менее, безусловно, хороший метод для его настройки
  • 0
    Вы правы. Не цепочка, поэтому не действительный плагин. Немного улучшили код, переместив декремент в состояние.
5

Если вы не хотите сохранять метод в jQuery.fn, вы можете использовать

[].reverse.call($('li'));
  • 0
    Это то, что я искал.
4

Нужно сделать обратное на $.each, поэтому я использовал идею Vinay:

//jQuery.each(collection, callback) =>
$.each($(collection).get().reverse(), callback func() {});

работал красиво, спасибо

  • 0
    Это не правильно; это должен быть только $.each(collection.reverse(), ...) .
  • 0
    @Ben Alpert - ваш комментарий некорректен, потому что коллекция не является истинным массивом
Показать ещё 1 комментарий
2

Вы не можете повторять итерацию с помощью каждой функции jQuery, но вы все равно можете использовать синтаксис jQuery.

Попробуйте следующее:

//get an array of the matching DOM elements   
var liItems = $("ul#myUL li").get();

//iterate through this array in reverse order    
for(var i = liItems.length - 1; i >= 0; --i)
{
  //do Something
}
1

Я нашел Array.prototype.reverse неудачным с объектами, поэтому я использовал новую функцию jQuery для использования в качестве альтернативы: jQuery.eachBack(). Он выполняет итерацию, поскольку обычный jQuery.each() будет и сохраняет каждый ключ в массив. Затем он меняет этот массив и выполняет обратный вызов исходного массива/объекта в порядке обратных ключей.

jQuery.eachBack=function (obj, callback) {
    var revKeys=[]; $.each(obj,function(rind,rval){revKeys.push(rind);}); 
    revKeys.reverse();
    $.each(revKeys,function (kind,i){
        if(callback.call(obj[i], i, obj[i]) === false) {    return false;}
    });
    return obj;
}   
jQuery.fn.eachBack=function (callback,args) {
    return jQuery.eachBack(this, callback, args);
}
0

Я понимаю, что jQuery поддерживает и поощряет плагины. Тем не менее, вы можете найти эту статью релевантной: Не изменяйте объекты, которые у вас нет. В этом случае, по крайней мере, я решил не распространять jQuery на случай, когда другой плагин определяет обратное по-разному.

Здесь простое решение, которое не расширяет объект jQuery.

function jqueryReverse( set ) {

    return [].reverse.call( set );
}

console.log( jqueryReverse( $( 'li' ) ) );
-2

Вы также можете попробовать

var arr = [].reverse.call($('li'))
arr.each(function(){ ... })
-2

Я думаю, вам нужно

.parentsUntill()
  • 1
    Почему вы так думаете? И как бы вы использовали это?
  • 1
    parentsUntill() даже написано неправильно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню