jQuery füge div als bestimmten Index ein

77

Sagen Sie, ich habe das:

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

Aber sagen wir, ich wollte ein neues Div willkürlich einfügen, basierend auf einem Index, den ich liefere.

Angenommen, ich habe den Index zum Einfügen von 0 angegeben. Das Ergebnis sollte sein:

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

und wenn ich einen Index zum Einfügen von 2 hätte, wäre das Ergebnis.

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

und wenn ich einen Index von 1 gebe, wäre das Ergebnis:

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

Vergessen Sie einfach das Format des letzten Beispiels. Das einfache Kopieren und Einfügen von HTML-Code auf dieser Website ist schrecklich genug, um mich zum Schreien zu bringen und mir die Haare auszureißen, und ich möchte keine Zeit mehr damit verbringen, mich damit zu beschäftigen!

DantheMan
quelle

Antworten:

82

Als Funktion mit etwas besserer Handhabung von 0:

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


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

BEARBEITEN: Klammer im n-ten Kind-Selektor hinzugefügt, um NaN-Fehler zu vermeiden. @hofnarwillie

Andy Gaskell
quelle
2
Vielleicht möchten Sie .before()stattdessen verwenden .append();)
Reigel
2
Sie sollten verwenden, $("#controller > div:nth-child(" + i + ")").before("<div>great things</div>");da sonst das neue Element möglicherweise mehrmals eingefügt wird, bei Kindern von Kindern von#controller
squarebracket
1
Dies schlägt im zweiten Beispiel stillschweigend fehl. An Position 2 befindet sich kein Element, daher muss kein Element zuvor eingefügt werden. Da Sie bereits Position 0 erreichen und diese separat behandeln, sollte dies funktionieren:$("#controller div:nth-child(" + i - 1 + ")").after("<div>great things</div>");
John H
3
Würde nicht eq(i)den gleichen Zweck erfüllen wie nth-child(" + i - 1 + ")?
MCB
1
müssen biegen :nth-child(" + i - 1 + ")"in :nth-child(" + (i - 1) + ")"sonst können Sie ein NaN Problem zu bekommen. Das Update wurde zur Antwort hinzugefügt.
Hofnarwillie
55

Ich hatte ein ähnliches Problem. Leider hat keine der Lösungen für mich funktioniert. Also habe ich es so codiert:

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;
}

Beispiele für das Problem:

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

Hier sind einige Beispiele aus meinen 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>");

Bearbeiten: Es behandelt jetzt alle negativen Indizes elegant.

Benjamin Gudehus
quelle
tolle Methode! Danke dafür. steckte es ein und es funktionierte wie ein Zauber.
Brad Goss
1
var lastIndex = this.children (). size (); funktioniert nicht mehr - benutze this.children (). length; stattdessen.
Bibamann
7

Ich fand, dass die aufgeführten Lösungen nicht funktionierten oder zu kompliziert waren. Sie müssen lediglich die Richtung bestimmen, aus der Sie anhängen. Hier ist etwas Einfaches, das in OOP-Form für jQuery geschrieben wurde.

$.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;
};

Sie können das Obige einfach mit einer einfachen Syntax verwenden.

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

Derzeit wird dies in einem Visual Editor-Projekt verwendet, in dem Tonnen von Daten per Drag & Drop verschoben werden. Alles funktioniert super.


Bearbeiten: Ich habe eine interaktive Live-CodePen-Demo hinzugefügt, in der Sie mit der oben genannten Lösung http://codepen.io/ashblue/full/ktwbe spielen können

Aschblau
quelle
1
Ich liebe die Einfachheit Ihrer Lösung Ash - gute Arbeit. Es funktioniert auch gut für mich.
Graham Ashton
Ich habe das obige Beispiel aktualisiert, um eine CodePen-Demo codepen.io/ashblue/full/ktwbe
Ash Blue
Tauschen Sie nicht einfach Elemente aus, ohne das Einfügen neuer Elemente zu unterstützen?
DarkNeuron
@DarkNeuron Sie können so viele Elemente einfügen und verschieben, wie Sie möchten. Schauen Sie sich den CodePen für eine interaktive Demo an.
Ash Blue
Dies ist eher so setIndex: Es verschiebt vorhandene Elemente. Dadurch wird kein Element an einem bestimmten Index eingefügt (z. B. kann das übergeordnete Element leer sein).
NateS
6

Benutze mein einfaches Plugin 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));
        }
    };*

Jetzt :

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

Oder :

$('<li>fgdf</li>').appendToWithIndex('ul',0)
Abdennour TOUMI
quelle
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 );
oLinkWebDevelopment
quelle
0

Wenn Sie dies häufig tun müssen, können Sie es in eine kleine Funktion einwickeln:

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

Wenn Sie über diese temporäre ID besorgt sind, können Sie einen letzten Schritt hinzufügen, um sie zu entfernen.

Bearbeiten: Aktualisiert, um Fälle von null Kindern zu behandeln, und n > aktuelle Anzahl von Divs angegeben.

Ken Redler
quelle
Das Problem wäre, wenn der $('#controller')keine Kinder hat, dann würde diese Funktion nicht funktionieren ...addit(0)
Reigel
Reigel, das stimmt. Zum Spaß wollte ich unbedingt versuchen, (native) Bedingungen zu vermeiden. Diese aktualisierte Version scheint für die Grenzfälle zu funktionieren.
Ken Redler
0

Dieser funktioniert am besten für mich,

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);
                }

            }
        };
Phil Snook
quelle
2
Phil, kannst du bitte etwas näher auf deine Antwort eingehen? Manchmal trägt das Posten von nur Code ohne Erklärung nur zur Verwirrung bei.
Dwayne Charrington
0

Verwenden Sie .insertAfter () :

$('<div class="new">').insertAfter($('div.first'));
yPhil
quelle
-1

Sie können immer prepend ('# div') verwenden.

Ex.

$(document).ready(function(){

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

});​

Das würde "#new" vor "#first" setzen. Ich bin mir nicht sicher, ob Sie das wollen.

MoDFoX
quelle
3
Das kümmert sich um den 0. Fall. Was ist mit der 2. Position? Er möchte in der Lage sein, anhand der Nummer anzugeben, wo das Div in die Liste der Divs eingefügt werden soll
Tommy