jQuery вставити div як певний індекс


78

Скажімо, у мене є таке:

<div id="controller">
 <div id="first">1</div>
 <div id="second>2</div>
</div>

але кажу, що я хотів вставити новий div довільно на основі індексу, який я надаю.

Скажімо, я дав індекс для вставки 0, результат повинен бути:

<div id="controller">
  <div id="new">new</div>
  <div id="first">1</div>
  <div id="second">2</div>
</div>

і якщо у мене є індекс для вставки 2, результат буде.

<div id="controller">
  <div id="first">1</div>
  <div id="second">2</div>
  <div id="new">new</div>
</div>

і якщо я дам індекс 1, результат буде:

<div id="controller">
  <div id="first">1</div>
  <div id="new">new</div>
  <div id="second">2</div>
</div>

просто забудьте формат останнього прикладу. Простий акт копіювання та вставки HTML-коду на цей сайт є досить жахливим, щоб змусити мене кричати і виривати волосся, і я не хочу витрачати більше часу на це!

Відповіді:


82

Як функція з трохи кращою обробкою 0:

function insertAtIndex(i) {
    if(i === 0) {
     $("#controller").prepend("<div>okay things</div>");        
     return;
    }


    $("#controller > div:nth-child(" + (i) + ")").after("<div>great things</div>");
}

РЕДАГУВАТИ: Додано дужки в селектор n-го потомка, щоб уникнути помилок NaN. @hofnarwillie


2
Ви можете використати .before()замість .append();)
Рейгель

2
Вам слід скористатися, $("#controller > div:nth-child(" + i + ")").before("<div>great things</div>");оскільки інакше новий елемент може вставлятися кілька разів, у #controller
дочірні дочірні

1
Для другого прикладу це мовчки не вдасться. У позиції 2 немає елемента, отже, немає елемента, який потрібно вставити раніше. Оскільки ви вже ловите позицію 0 і обробляєте її окремо, це має спрацювати:$("#controller div:nth-child(" + i - 1 + ")").after("<div>great things</div>");
John H

3
Чи не буде eq(i)служити тій самій меті, що і nth-child(" + i - 1 + ")?
MCB

1
потрібно перетворити :nth-child(" + i - 1 + ")"на, :nth-child(" + (i - 1) + ")"інакше ви можете отримати проблему з NaN. Додано виправлення до відповіді.
hofnarwillie

55

У мене була подібна проблема. На жаль, жодне з рішень не спрацювало для мене. Тож я кодував це так:

jQuery.fn.insertAt = function(index, element) {
  var lastIndex = this.children().size();
  if (index < 0) {
    index = Math.max(0, lastIndex + 1 + index);
  }
  this.append(element);
  if (index < lastIndex) {
    this.children().eq(index).before(this.children().last());
  }
  return this;
}

Приклади проблеми:

$("#controller").insertAt(0, "<div>first insert</div>");
$("#controller").insertAt(-1, "<div>append</div>");
$("#controller").insertAt(1, "<div>insert at second position</div>");

Ось кілька прикладів, взятих з моїх unittests:

$("<ul/>").insertAt(0, "<li>0</li>");
$("<ul/>").insertAt(0, "<li>0</li>").insertAt(1, "<li>1</li>");
$("<ul/>").insertAt(-1, "<li>-1</li>");
$("<ul/>").insertAt(-1, "<li>-1</li>").insertAt(0, "<li>0</li>");
$("<ul/>").insertAt(0, "<li>0</li>").insertAt(-1, "<li>-1</li>");
$("<ul/>").insertAt(-1, "<li>-1</li>").insertAt(1, "<li>1</li>");
$("<ul/>").insertAt(-1, "<li>-1</li>").insertAt(99, "<li>99</li>");
$("<ul/>").insertAt(0, "<li>0</li>").insertAt(2, "<li>2</li>").insertAt(1, "<li>1</li>");
$("<ul/>").insertAt(0, "<li>0</li>").insertAt(1, "<li>1</li>").insertAt(-1, "<li>-1</li>");
$("<ul/>").insertAt(0, "<li>0</li>").insertAt(1, "<li>1</li>").insertAt(-2, "<li>-2</li>");
$("<ul/>").insertAt(0, "<li>0</li>").insertAt(1, "<li>1</li>").insertAt(-3, "<li>-3</li>");
$("<ul/>").insertAt(0, "<li>0</li>").insertAt(1, "<li>1</li>").insertAt(-99, "<li>-99</li>");

Редагувати: Зараз він витончено обробляє всі негативні індізи.


чудовий метод! дякую за це. підключив його до мережі, і це спрацювало як шарм.
Бред Госс

1
var lastIndex = this.children (). size (); більше не працює - використовуйте this.children (). length; замість цього.
bibamann

8

Я виявив, що перелічені рішення не працювали або були надто складними. Все, що вам потрібно зробити, це визначити напрямок, з якого ви додаєтеся. Ось щось просте, написане в ООП для jQuery.

$.fn.insertIndex = function (i) {
    // The element we want to swap with
    var $target = this.parent().children().eq(i);

    // Determine the direction of the appended index so we know what side to place it on
    if (this.index() > i) {
        $target.before(this);
    } else {
        $target.after(this);
    }

    return this;
};

Ви можете просто використовувати вищезазначене з деяким простим синтаксисом.

$('#myListItem').insertIndex(2);

В даний час я використовую це у проекті візуального редактора, переміщуючи безліч даних за допомогою перетягування. Все працює чудово.


Змінити: Я додав живий інтерактивний CodePen демо , де ви можете грати з зазначеним вище розчином http://codepen.io/ashblue/full/ktwbe


1
Мені подобається простота вашого рішення Зола - приємна робота. Це добре працює і для мене.
Грем Ештон

Я оновив наведений вище приклад, включивши демонстраційний код
Ash Blue

Це не просто обмін елементами навколо, фактично не підтримуючи вставлення нових?
ТемнийНейрон

@DarkNeuron Ви можете вставляти та переміщувати скільки завгодно елементів навколо. Перегляньте CodePen для інтерактивного демо.
Ash Blue

Це більше схоже setIndex: воно переміщує існуючі елементи навколо. Це не вставка елемента з певним індексом (наприклад, батьківський елемент може бути порожнім).
NateS

6

Використовуйте мій простий плагін Append With Index :

$.fn.appendToWithIndex=function(to,index){
        if(! to instanceof jQuery){
            to=$(to);
        };
        if(index===0){
            $(this).prependTo(to)
        }else{
            $(this).insertAfter(to.children().eq(index-1));
        }
    };*

Зараз:

$('<li>fgdf</li>').appendToWithIndex($('ul'),4)

Або:

$('<li>fgdf</li>').appendToWithIndex('ul',0)

2
//jQuery plugin insertAtIndex included at bottom of post   

//usage:
$('#controller').insertAtIndex(index,'<div id="new">new</div>');

//original:
<div id="controller">
  <div id="first">1</div>
  <div id="second>2</div>
</div>

//example: use 0 or -int          
$('#controller').insertAtIndex(0,'<div id="new">new</div>');
  <div id="controller">
    <div id="new">new</div>
    <div id="first">1</div>
    <div id="second>2</div>
  </div>

//example: insert at any index     
$('#controller').insertAtIndex(1,'<div id="new">new</div>');
     <div id="controller">
        <div id="first">1</div>
        <div id="new">new</div>
        <div id="second>2</div>
     </div>

//example: handles out of range index by appending        
$('#controller').insertAtIndex(2,'<div id="new">new</div>');
      <div id="controller">
          <div id="first">1</div>
          <div id="second>2</div>
          <div id="new">new</div>
      </div>

/**!
 * jQuery insertAtIndex
 * project-site: https://github.com/oberlinkwebdev/jQuery.insertAtIndex
 * @author: Jesse Oberlin
 * @version 1.0
 * Copyright 2012, Jesse Oberlin
 * Dual licensed under the MIT or GPL Version 2 licenses.
*/

(function ($) { 
$.fn.insertAtIndex = function(index,selector){
    var opts = $.extend({
        index: 0,
        selector: '<div/>'
    }, {index: index, selector: selector});
    return this.each(function() {
        var p = $(this);  
        var i = ($.isNumeric(opts.index) ? parseInt(opts.index) : 0);
        if(i <= 0)
            p.prepend(opts.selector);
        else if( i > p.children().length-1 )
            p.append(opts.selector);
        else
            p.children().eq(i).before(opts.selector);       
    });
};  
})( jQuery );

0

Якщо вам потрібно зробити це багато, ви можете обернути це в невелику функцію:

var addit = function(n){
  $('#controller').append('<div id="temp">AAA</div>')
    .stop()
    .children('div:eq('+n+')')
    .before( $('#temp') );
} 

addit(2); // adds a new div at position 2 (zero-indexed)
addit(10); // new div always last if n greater than number of divs
addit(0); // new div is the only div if there are no child divs

Якщо вас турбує цей тимчасовий посвідчення особи, ви можете додати останній крок, щоб видалити його.

Редагувати: оновлено, щоб обробляти випадки нульових дочірніх елементів, і вказано n > поточну кількість div.


проблема полягала б у тому, що у $('#controller')дітей немає дітей, тоді ця функція не працювала б ...addit(0)
Рейгель

Рейгель, це правда. Для розваги я дуже хотів спробувати уникнути будь-якого (рідного) умовного. Цей оновлений, здається, працює для прикордонних справ.
Ken Redler

0

Цей найкраще працює для мене,

function SetElementIndex(element, index) {
            var Children = $(element).parent().children();
            var target = Children[index];

            if ($(element).index() > index) {
                if (target == null) {
                    target = Children[0];
                }
                if (target != element && target != null) {
                    $(target).before(element);
                }
            } else {
                if (target == null) {
                    target = Children[Children.length - 1];
                }
                if (target != element && target != null) {
                    $(target).after(element);
                }

            }
        };

2
Філе, ти можеш трохи детальніше розказати свою відповідь? Іноді розміщення просто коду без пояснень просто додає сум’яття.
Дуейн Чаррінгтон


-1

Ви завжди можете використовувати prepend ('# div');

напр.

$(document).ready(function(){

$('#first').prepend('<div id="new">New</div>');

});​

Це ставило б "#new" перед "#first" Не впевнений, що це те, що ти хочеш.


3
Це піклується про 0-й випадок. А як щодо 2-ї позиції? Він хоче мати можливість вказати за номером, куди вставити div у списку div
Tommy
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.