Как переместить элемент в другой элемент?

1689

Я хотел бы переместить один элемент DIV в другой. Например, я хочу переместить это (включая всех детей):

<div id="source">
...
</div>

в это:

<div id="destination">
...
</div>

так что у меня так:

<div id="destination">
  <div id="source">
    ...
  </div>
</div>
Марк Ричман
источник
21
Просто используйте $ (target_element) .append (to_be_inserted_element);
Мохаммед Ариб Сиддики
2
Или: destination.appendChild (source) с использованием простого javascript
Люк
мы можем достичь этого с помощью CSS? это возможно ?
РаджКумар Самала
6
@RajKumarSamala CSS не может изменить структуру HTML, только его представление.
Марк Ричман

Ответы:

39

Когда-нибудь пробовал простой JavaScript ... destination.appendChild(source);?

onclick = function(){ destination.appendChild(source); }
div{ margin: .1em; } 
#destination{ border: solid 1px red; }
#source {border: solid 1px gray; }
<!DOCTYPE html>
<html>

 <body>

  <div id="destination">
   ###
  </div>
  <div id="source">
   ***
  </div>

 </body>
</html>

Беким Бакай
источник
* кто-то поставил перед глобальным событием onclick фрагмента демонстрации ключевое слово varв своей попытке улучшить пост - но это неправильно!
Беким Бакай
6
Удивительно, как люди все еще думают, что jQuery равен JavaScript. Нет необходимости в jQuery в 2017 году, правда.
nkkollaw
2
нет необходимости в jquery в 2017 году, но иногда это помогает использовать что-то более легкое и похожее для задач, которые вы делаете снова и снова в каждом отдельном проекте. Я использую Cash-Dom как простой способ прослушивания событий document.ready, window.load в кросс-браузерной форме. очень просто.
eballeste
1
Меняя это на принятый ответ, теперь, когда наступил 2020 год :)
Марк Ричман
1
Удивительно, как люди все еще думают, что jQuery равен JavaScript. В 2020 году больше нет необходимости в jQuery.
ii iml0sto1
1794

Вы можете использовать appendToфункцию (которая добавляет в конец элемента):

$("#source").appendTo("#destination");

В качестве альтернативы вы можете использовать prependToфункцию (которая добавляет в начало элемента):

$("#source").prependTo("#destination");

Пример:

Эндрю Хэйр
источник
23
Предупреждение о том, что в jQuery mobile это может работать некорректно, поскольку вместо этого может быть создана другая копия элемента.
Джордан Рейтер
32
appenTo создает копию или фактически перемещает весь div к месту назначения? (потому что, если он скопирует, он вызовет ошибки при вызове div по id)
50
Вот отличная статья об извлечении, замене и перемещении элементов в jQuery: elated.com/articles/jquery-removing-replacing-moving-elements
xhh
42
Обратите внимание на документацию jQuery для appendTo, в которой говорится, что элемент перемещен: it will be moved into the target (not cloned) and a new set consisting of the inserted element is returned- api.jquery.com/appendto
John K
15
Вы не двигаете это, просто добавляете. Ниже ответ делает правильное движение.
Аарон
913

мое решение:

ШАГ:

jQuery("#NodesToMove").detach().appendTo('#DestinationContainerNode')

COPY:

jQuery("#NodesToMove").appendTo('#DestinationContainerNode')

Обратите внимание на использование .detach (). При копировании будьте осторожны, чтобы не дублировать идентификаторы.

Алехандро Иллекас
источник
86
Лучший ответ. Принятый ответ создает копию, но не перемещает элемент, как требует вопрос.
paulscode
97
Извините, но принятый Эндрю Хэром правильный ответ - отсоединение не нужно. Попробуйте это в JSFiddle от Pixic выше - если вы удаляете вызовы detach, он работает точно так же, то есть выполняет перемещение, а не копию. Вот ответвление только с одним изменением: jsfiddle.net/D46y5 Как описано в API: api.jquery.com/appendTo : «Если элемент, выбранный таким образом, вставляется в одно место в другом месте в DOM, он будет перемещен в цель (не клонировано) и возвращается новый набор, состоящий из вставленного элемента "
Джон - Не число
8
@ John-NotANumber прав - detach () здесь не нужен. Принятый ответ - лучший, вам просто нужно правильно прочитать документацию.
Леонард Чаллис
11
В документации appendTo также говорится: «Если имеется более одного целевого элемента, однако, клонированные копии вставленного элемента будут созданы для каждой цели после первой, и этот новый набор (исходный элемент плюс клоны) будет возвращен». Так что в общем случае это решение МОЖЕТ также создавать копии!
Винсент Пазеллер
Великий! Или вы можете использовать это, чтобы быть более точным в том, куда двигаться$('#nodeToMove').insertAfter('#insertAfterThisElement');
Виктор Августо,
108

Я просто использовал:

$('#source').prependTo('#destination');

Который я схватил отсюда .

kjc26ster
источник
7
Ну, отсоединение полезно, когда вы хотите удержать элемент и вставить его позже, но в вашем примере вы все равно вставите его немедленно.
Тим Бюте
1
Боюсь, я не совсем понимаю, к чему вы клоните, не могли бы вы предоставить пример кода?
kjc26ster
1
Я имею в виду, prependTo, отсоединяет элемент от его исходного положения и вставляет его в новое. Функция detach, с другой стороны, просто отсоединяет выбранный элемент, и вы можете сохранить его в переменной, чтобы вставить его в DOM в более поздний момент времени. Дело в том, что ваш звонок отсоединения не нужен. Удалите его, и вы добьетесь того же эффекта.
Тим Бют
1
Невероятно, что изменения полностью изменили этот ответ до такой степени, что еще один ответ был добавлен год спустя (идентично оригиналу) и получил более 800 голосов ...
hlscalon
96

Как насчет решения JavaScript ?

// Declare a fragment:
var fragment = document.createDocumentFragment();

// Append desired element to the fragment:
fragment.appendChild(document.getElementById('source'));

// Append fragment to desired element:
document.getElementById('destination').appendChild(fragment);

Проверьте это.

Али Бассам
источник
8
Зачем использовать createDocumentFragment вместо простого document.getElementById ('destination'). AppendChild (document.getElementById ('source'))?
Гунар Гесснер
6
@ GunarC.Gessner, если вам нужно изменить исходный объект перед добавлением его к целевому объекту, тогда лучше всего использовать фрагмент, который является воображаемым объектом и не является частью дерева DOM, вы получаете лучшую производительность при изменении исходный объект, когда он был перемещен из своего исходного места (теперь он внутри фрагмента), а не изменяет его в своем первоначальном месте перед добавлением.
Али Бассам
5
Я хочу добавить для актуальности предложения чистого JavaScript-решения. Не следует предполагать, что jQuery всегда используется
Александр Фрадиани
1
Вопрос: При добавлении дочернего узла мы теряем вложенные события?
Jimasun
1
Ответ на мой собственный вопрос - да, он сохраняет прикрепленные события.
Jimasun
95

Если в том месте, divкуда вы хотите поместить свой элемент, есть содержимое, и вы хотите, чтобы элемент отображался после основного содержимого:

  $("#destination").append($("#source"));

Если в том месте, divкуда вы хотите поместить свой элемент, есть содержимое, и вы хотите показать элемент перед основным содержимым:

$("#destination").prepend($("#source"));

Если место, divкуда вы хотите поместить свой элемент, пусто или вы хотите заменить его полностью:

$("#element").html('<div id="source">...</div>');

Если вы хотите продублировать элемент перед любым из вышеперечисленных:

$("#destination").append($("#source").clone());
// etc.
sbaaaang
источник
Я нахожу все жирным шрифтом немного трудным для чтения, но это самый информативный ответ, так что он получает мое одобрение.
Майкл Шепер
32

Ты можешь использовать:

Вставить после,

jQuery("#source").insertAfter("#destination");

Чтобы вставить внутрь другого элемента,

jQuery("#source").appendTo("#destination");
Subrahmanyam
источник
20

Если вам нужна быстрая демонстрация и более подробная информация о том, как вы перемещаете элементы, попробуйте эту ссылку:

http://html-tuts.com/move-div-in-another-div-with-jquery


Вот краткий пример:

Чтобы переместить элемент выше:

$('.whatToMove').insertBefore('.whereToMove');

Чтобы переместить ПОСЛЕ элемента:

$('.whatToMove').insertAfter('.whereToMove');

Чтобы переместиться внутрь элемента, НАД ВСЕМИ элементами внутри этого контейнера:

$('.whatToMove').prependTo('.whereToMove');

Чтобы переместиться внутрь элемента, ПОСЛЕ ВСЕХ элементов внутри этого контейнера:

$('.whatToMove').appendTo('.whereToMove');
Дэн
источник
19

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

 jQuery("#source")
       .detach()
       .appendTo('#destination');

попробуйте работать codepen

Subodh Ghulaxe
источник
11

Старый вопрос, но он попал сюда, потому что мне нужно переместить контент из одного контейнера в другой, включая всех слушателей событий .

У jQuery нет способа сделать это, но есть стандартная функция DOM appendChild.

//assuming only one .source and one .target
$('.source').on('click',function(){console.log('I am clicked');});
$('.target')[0].appendChild($('.source')[0]);

Использование appendChild удаляет .source и помещает его в цель, включая его прослушиватели событий: https://developer.mozilla.org/en-US/docs/Web/API/Node.appendChild

HMR
источник
6

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

$("#destination").html($("#source"))

Но это полностью перезапишет все, что у вас есть #destination.

Тамас
источник
2
И разбить слушателей событий на перемещенный элемент.
Игорь Помаранский
4

Я заметил огромную утечку памяти и разницу в производительности между insertAfter& afterили insertBefore& before. Если у вас тонны DOM-элементов или вам нужно использовать after()или before()внутри события MouseMove , память браузера, вероятно, увеличится, и следующие операции будут выполняться очень медленно.

Решение, которое я только что испытал, состоит в том, чтобы вместо этого использовать insertBefore before()и insertAfter after().

спецназовская
источник
Это похоже на проблему, связанную с реализацией движка JavaScript. В какой версии браузера и движке JS вы это видите?
Марк Ричман
1
Я использую Chrome версии 36.0.1985.125 и использую jQuery v1.11.1. Я связываю функцию с событием mousemove, которая перемещает простой DIV вниз или вверх по элементу, над которым находится мышь. Следовательно, это событие и функция выполняются, пока вы перетаскиваете курсор. Утечка памяти происходит с помощью after () и before (), если вы перемещаете курсор на 30 секунд +, и исчезает, если я просто использую insertAfter & insertBefore.
спецназ
1
Я бы открыл ошибку с Google на этом.
Марк Ричман
2

Вы можете использовать чистый JavaScript, используя appendChild()метод ...

Метод appendChild () добавляет узел в качестве последнего дочернего элемента узла.

Совет. Если вы хотите создать новый абзац с текстом, не забудьте создать текст как узел текста, который вы добавляете к абзацу, а затем добавьте абзац в документ.

Вы также можете использовать этот метод для перемещения элемента из одного элемента в другой.

Совет: Используйте метод insertBefore () для вставки нового дочернего узла перед указанным существующим дочерним узлом.

Таким образом, вы можете сделать это, чтобы выполнить работу, это то, что я создал для вас, используя appendChild(), запустите и посмотрите, как это работает для вашего случая:

function appendIt() {
  var source = document.getElementById("source");
  document.getElementById("destination").appendChild(source);
}
#source {
  color: white;
  background: green;
  padding: 4px 8px;
}

#destination {
  color: white;
  background: red;
  padding: 4px 8px;
}

button {
  margin-top: 20px;
}
<div id="source">
  <p>Source</p>
</div>

<div id="destination">
  <p>Destination</p>
</div>

<button onclick="appendIt()">Move Element</button>

Алиреза
источник
0

Для полноты картины есть другой подход wrap()или wrapAll()упомянутый в этой статье . Таким образом, вопрос OP мог бы быть решен с помощью этого (то есть, предполагая, что <div id="destination" />он еще не существует, следующий подход создаст такую ​​обертку с нуля - у OP не было ясности относительно того, существует ли обертка уже или нет):

$("#source").wrap('<div id="destination" />')
// or
$(".source").wrapAll('<div id="destination" />')

Это звучит многообещающе. Тем не менее, когда я пытался сделать $("[id^=row]").wrapAll("<fieldset></fieldset>")несколько вложенных структур, как это:

<div id="row1">
    <label>Name</label>
    <input ...>
</div>

Это правильно оборачивает те <div>...</div>и <input>...</input>НО ИНАЧЕ пропускает <label>...</label>. Поэтому я в конечном итоге использовал явное $("row1").append("#a_predefined_fieldset")вместо этого. Итак, YMMV.

RayLuo
источник