Используйте JQuery для переноса нескольких наборов элементов в Div

Я работаю над выпадающим меню и мне нужно изменить существующую HTML-разметку с помощью JQuery, чтобы она соответствовала дизайну.

Вот упрощенный пример: Оберните все "ul", которые содержат более одного "li" в div (в том же самом div, НЕ один div для каждого UL).

<ul>
    <li>foo</li>
</ul>
<ul>
    <li>foo</li>
    <li>foo</li>
</ul>
<ul>
    <li>foo</li>
    <li>foo</li>
</ul>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>

<script>
my_selection = [];
i = 0;
// find all ul's that have more than one li
$("ul").each(function(){
    if($(this).find("li").length > 1){
        // add this to my_selection
        my_selection[i] = $(this);
        i++;
    } // if
}); // each

// wrap my_selection in div tags
$(my_selection).wrapAll(document.createElement("div"));
</script>

Приведенный выше код дает эту ошибку Firebug:

"Узел не может быть вставлен в указанную точку в иерархии" код: "3"

Как я могу заставить это работать?

6 ответов

Решение

Это был бы более чистый подход:

$('ul:has(li)').wrap('<div></div>');

Во-первых, вам не нужно создавать узел, просто предоставьте строку переноса для jQuery. Во-вторых, используйте :has Селектор в этом случае, чтобы сократить each функциональность в вашем примере. Наконец, (это будет зависеть от вашей предполагаемой функциональности) вы можете использовать wrap вместо wrapAll,

РЕДАКТИРОВАТЬ: Другой вариант будет подходить к нему с другой стороны. Получить <li> теги затем захватить <ul> родитель:

$('li:not(:only-child)').parent().filter('ul').wrap('<div></div>');

Это немного взломать.

<script>
jQuery( function() {
    my_selection = [];

    i = 0;
    n = 0;
    jQuery( 'ul' ).each( function() {
        var ul = jQuery( this );
        if ( ul.children().length > 1 ) {
            my_selection[n++] = 'ul:eq(' + i + ')';
        }
        ++i;
    } );

    jQuery( my_selection.join( ',' ) ).wrapAll( document.createElement( 'div' ) );
} );
</script>

Я не уверен, что jQuery может принимать массивы в качестве селекторов. В $(my_selection)my_selection - это не объект jQuery, а массив объектов. Вы можете сначала попытаться сгенерировать объекты jQuery, используя var my_selection = $(''); ... my_selection.add($(this));,

Кроме того, с .wrapAll() Метод, вы можете просто использовать: .wrapAll('<div></div>');,

В вашем коде есть ошибка, пытающаяся обернуть вашу LI с помощью DIV.

<script>
my_selection = [];
i = 0;
// find all ul's that have more than one li
$("ul").each(function() {
    var $ul = $(this);
    if ($ul.find("li").length > 1){
        // add this to my_selection
        my_selection[i] = $ul;
        i++;
    } // if
});

// wrap my_selection in div tags
$(my_selection).wrap(document.createElement("div"));
</script>

Я был немного занят, когда я ответил на этот вопрос, извините за все проблемы. Это следующее решает проблему правильно.

<script type="text/javascript">
jQuery( function() {
    jQuery( 'ul' ).find( 'li:eq(1)' ).parent().wrapAll( '<div></div>' );
} );
</script>

Изменить: я изменил li:gt(0) на li: eq (1), они оба работают, но один имеет больше смысла.

Все просто, он проходит через всех ульов и их детей, пытается схватить второго ребенка. Если 2-й дочерний элемент найден, он возвращается к своему родителю и добавляет его в метод wrapAll.

Редактировать: Похоже, что если вы редактируете свое сообщение более 8 раз, оно становится интересным.

Это все отличные ответы. Но я заметил, что ваш сценарий не находится внутри $(document).ready(function(){...}) и вы, похоже, убедились, что эта ошибка все еще существует с другим кодом, который не был включен в готовую функцию.

Я попробовал и обнаружил, что код Уильяма сработал (+1 к нему), но из-за моего OCD я немного его почистил

$(document).ready(function(){
 my_selection = [];
 $('ul').each(function(i){
  if ($(this).find('li').length > 1 ){
   my_selection.push(['ul:eq(' + i + ')']);
  }
 });
 $( my_selection.join(',')).wrapAll('<div class="wrapper"></div>');
})
Другие вопросы по тегам