У меня есть следующий код, в котором синие цветные поля в левом тексте помещаются внутри квадратов после нажатия кнопки. В моем реальном коде это будет работать так: будет раскрывающийся список некоторых элементов, и я получу значения синих полей (например, H1 Text, H2 Text и т. д.) в зависимости от того, что выбрано пользователем из раскрывающийся список. Таким образом, в основном я буду динамически генерировать элементы div, связанные с синими прямоугольниками, и общее количество блоков (и значение внутри них) зависит от того, сколько значений возвращается в зависимости от выбора элемента из раскрывающегося списка. (Эта часть здесь не показана, и я просто жестко запрограммировал синие поля, поскольку это не имеет отношения к моему вопросу).
Мой вопрос:
Если я захочу на лету создать дополнительные синие ящики, можно ли этого добиться? Например, я хочу создать синее поле со значением F6 Text в качестве значения и поместить его под синее поле с надписью G6 Text. Можно ли его создать? Это будет добавление такого нового div <div data-id = "13"><span data-id = "13" class = "words">F6 Text</span></div> чуть ниже <div data-id = "12"><span data-id = "12" class = "words">G6 Text</span></div> внутри <div id = "phrase">
Кроме того, я хотел бы создать просто пустое поле без какого-либо значения, поэтому, если у меня в div есть элементы до F6 Text, это будет выглядеть как <div data-id = "14"><span data-id = "12" class = "words"></span></div>.
Мне интересно, нужна ли мне где-нибудь кнопка, где мне нужно показать всплывающее диалоговое окно, спрашивающее пользователя, какое значение необходимо, а затем добавить div к приведенным выше элементам div, или есть ли лучший способ справиться с этим?
Возвращаясь к объяснению раскрывающегося списка, о котором я упоминал в первом абзаце, я изначально думал о том, чтобы эти поля или просто текст отображался в текстовой области, разделенной запятой, а затем пользователь мог просто нажать кнопку, и текст будет перемещаться. внутри квадратов, но у меня не может быть элементов div внутри текстовой области, поэтому я думаю, что этот подход не сработает.
$(".words").draggable({
revert: function (event, ui) {
var bRevertingPhrase = this.closest("#drop-em");
if (!bRevertingPhrase.length) {
var phraseID = $(this).data("id");
var phraseHomeID = $(this).parent().data("id");
//If the child and parent ids don't match, we move the child to the correct parent
if (phraseID !== phraseHomeID) {
var correctCell = $("#phrase").find("div[data-id='" + phraseID + "']");
correctCell.prepend(this);
}
}
return !event;
}
});
$("#drop-em > div").droppable({
drop: function (ev, ui) {
$(ui.draggable)
.detach()
.css({ top: 0, left: 0 })
.appendTo($(this).find(".content:empty"));
$("#move-text").addClass("disabled");
}
});
$("#phrase > div").droppable({
drop: function (ev, ui) {
$(ui.draggable).detach().css({ top: 0, left: 0 }).prependTo(this);
}
});
const myButton = document.querySelector("#move-text");
myButton.addEventListener(
"click",
() => {
fill();
},
{
once: true
}
);
var reOrder = [];
function fill() {
const cells = document.querySelectorAll("#phrase > div > span");
var newLoc = "";
myButton.classList.add("disabled");
cells.forEach((cell, index) => {
newLoc = document.querySelector(
".item:nth-child(" + reOrder[index] + ") .content "
);
newLoc.append(cell);
newLoc.classList.add("moved");
});
}
function reArrange() {
var limit1 = 85;
var limit2 = 91;
for (let loop = 0; loop < 8; loop++) {
for (let i = 0; i < 6; i++) {
reOrder.push(limit1 + i);
}
limit1 = limit1 - 12;
}
for (let loop = 0; loop < 8; loop++) {
for (let j = 0; j < 6; j++) {
reOrder.push(limit2 + j);
}
limit2 = limit2 - 12;
}
}
reArrange();html {
box-sizing: border-box;
}
*,
*:before,
*:after {
box-sizing: inherit;
}
body {
counter-reset: columnCount 1 alphaCount cellCount;
}
h1 {
text-align: center;
}
.wrap {
display: flex;
gap: 2rem;
position:relative;
padding-left:220px;
}
.grid {
margin: auto;
display: grid;
flex: 1 0 0;
grid-template-columns: repeat(12, 1fr);
padding-top: 1.5rem;
}
.item {
position: relative;
background-color: #f9f9f9;
border: 1px solid grey;
aspect-ratio: 1/1;
counter-increment: columnCount;
min-width: 0;
transition: background 1s ease;
}
.item:nth-of-type(12n + 1) {
counter-increment: alphaCount;
}
.item:nth-of-type(12n + 1)::before {
content: counter(alphaCount, upper-alpha);
position: absolute;
display: flex;
align-items: center;
top: 0;
bottom: 0;
left: -1.75rem;
color: red;
pointer-events: none;
}
.item:nth-of-type(n + 13)::after {
display: none;
}
.item::after {
content: counter(columnCount);
position: absolute;
left: 0;
right: 0;
text-align: center;
top: -1.75rem;
color: red;
pointer-events: none;
}
.content {
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
height: 100%;
overflow: auto;
color: #000;
padding: 1rem;
word-wrap: break-word;
counter-increment: cellCount;
}
.words {
cursor: move;
transition: padding 0.5s ease;
}
.content:has(.ui-draggable-dragging) {
overflow: visible;
}
.ui-droppable-active .content {
overflow: visible;
}
.words.ui-draggable-dragging {
background: blue;
padding: 5px 10px;
border-radius: 6px;
z-index: 999;
color: #fff;
display: block;
width: 50px;
height: 50px;
overflow: hidden;
}
#phrase {
position:absolute;
left:0;
top:0;
bottom:0;
color: #fff;
width:150px;
overflow:auto;
z-index: 2;
display: flex;
flex-direction: column;
margin:1rem 0 .5rem;
}
#phrase > div {
margin: 0 0 10px;
width:150px;
padding: 5px 10px;
background: #007bff;
border: 2px solid #007bff;
border-radius: 6px;
color: #fff;
}
#phrase > div:empty {
background: #fff;
border-style: dashed;
padding: 0px 25px;
min-height: 30px;
}
.moved {
animation: fade 3s ease;
}
@keyframes fade {
0% {
opacity: 0;
}
50% {
opacity: 1;
background: red;
}
}
.item .content::before {
content: counter(cellCount);
position: absolute;
top: 2px;
left: 2px;
font-size: smaller;
color: #666;
border-radius: 50%;
border: 1px solid red;
background: white;
width: 1.2rem;
height: 1, 2rem;
display: grid;
place-items: center;
}
#move-text.disabled{
cursor:none;
pointer-events:none;
opacity:0.5;
}
#phrase:has(.ui-droppable-active){
overflow:visible;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<!-- You'd need to set up something different for touch devices though -->
<h1>Drag and drop example </h1>
<button id = "move-text" type = "button">Move Text Content!</button>
<div class = "wrap">
<div id = "phrase">
<!-- remove whitespace from inside div html and then we can use :empty in css to change background -->
<div data-id = "1"><span data-id = "1" class = "words">H1 Text</span></div>
<div data-id = "2"><span data-id = "2" class = "words">H2 Text</span></div>
<div data-id = "3"><span data-id = "3" class = "words">H3 Text</span></div>
<div data-id = "4"><span data-id = "4" class = "words">H4 Text</span></div>
<div data-id = "5"><span data-id = "5" class = "words">H5 Text</span></div>
<div data-id = "6"><span data-id = "6" class = "words">H6 Text</span></div>
<div data-id = "7"><span data-id = "7" class = "words">G1 Text</span></div>
<div data-id = "8"><span data-id = "8" class = "words">G2 Text</span></div>
<div data-id = "9"><span data-id = "9" class = "words">G3 Text</span></div>
<div data-id = "10"><span data-id = "10" class = "words">G4 Text</span></div>
<div data-id = "11"><span data-id = "11" class = "words">G5 Text</span></div>
<div data-id = "12"><span data-id = "12" class = "words">G6 Text</span></div>
</div>
<div id = "drop-em" class = "grid">
<div class = "item">
<div class = "content"></div><!-- must have no spaces inside .content -->
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
<div class = "item">
<div class = "content"></div>
</div>
</div>
</div>


![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Можно динамически добавить еще один div, как показано в примере ниже. Я удалил сетку, так как ее не нужно демонстрировать. Я также сократил ваш код HTML и JavaScript до минимума.
Важная работа выполняется в прослушивателе событий addButton.
Существует несколько способов вычисления следующего идентификатора атрибута data-id. Я решил получить количество дочерних элементов div с идентификатором «фразы», используя childElementCount, а затем добавить к нему 1.
Вам следует проверить вновь созданный синий ящик в инструментах разработки, чтобы сравнить его с существующими синими ящиками и убедиться, что все классы и идентификаторы данных добавлены правильно.
После небольшой корректировки можно будет использовать код в прослушивателе событий для динамического создания всех синих прямоугольников. Вероятно, этот код стоит выделить в отдельную функцию.
Обратите внимание, что я снова вызываю функцию JQuery draggable() внутри прослушивателя событий с помощью:
$(".words").draggable();
чтобы добавить все правильные классы во вновь созданный синий ящик.
Этот метод должен дать вам представление о том, как подойти к остальной части вашей проблемы. Я уверен, что вы сможете получить текст синего поля из соответствующего элемента input.
$(".words").draggable();
const addButton = document.querySelector("#add-blue-box");
addButton.addEventListener(
"click", () => {
const phraseDiv = document.querySelector("#phrase");
let nextId = phraseDiv.childElementCount + 1;
const divElement = document.createElement("div");
const spanElement = document.createElement("span");
spanElement.textContent = "F6 Text";
spanElement.setAttribute('data-id', nextId);
spanElement.classList.add('words');
divElement.appendChild(spanElement);
divElement.setAttribute('data-id', nextId);
phraseDiv.appendChild(divElement);
$(".words").draggable();
});h1 {
text-align: center;
}
.wrap {
display: flex;
gap: 2rem;
position: relative;
padding-left: 220px;
height: 100vh;
}
#phrase {
position: absolute;
left: 0;
top: 0;
bottom: 0;
color: #fff;
width: 150px;
overflow: auto;
z-index: 2;
display: flex;
flex-direction: column;
margin: 1rem 0 .5rem;
}
#phrase>div {
margin: 0 0 10px;
width: 150px;
padding: 5px 10px;
background: #007bff;
border: 2px solid #007bff;
border-radius: 6px;
color: #fff;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<h1>Drag and drop example </h1>
<button id = "add-blue-box" type = "button">Add Blue Box</button>
<div class = "wrap">
<div id = "phrase">
<div data-id = "1"><span data-id = "1" class = "words">H1 Text</span></div>
<div data-id = "2"><span data-id = "2" class = "words">H2 Text</span></div>
<div data-id = "3"><span data-id = "3" class = "words">H3 Text</span></div>
<div data-id = "4"><span data-id = "4" class = "words">H4 Text</span></div>
<div data-id = "5"><span data-id = "5" class = "words">H5 Text</span></div>
<div data-id = "6"><span data-id = "6" class = "words">H6 Text</span></div>
</div>
</div>В качестве альтернативы, если вы действительно хотите сделать это с помощью JQuery (который представляет собой всего лишь библиотеку JavaScript), то одним из решений будет следующий фрагмент кода:
$(".words").draggable();
const addButton = document.querySelector("#add-blue-box");
addButton.addEventListener(
"click", () => {
let nextId = $("#phrase").children().length + 1;
let text1 = "F6";
let text2 = "Text";
$("<div>", {
"data-id": nextId
})
.append($("<span>", {
"data-id": nextId,
class: "words"
})
.text("Ln#" + text1 + " " + text2)
).appendTo($("#phrase"));
$(".words").draggable();
});h1 {
text-align: center;
}
.wrap {
display: flex;
gap: 2rem;
position: relative;
padding-left: 220px;
height: 100vh;
}
#phrase {
position: absolute;
left: 0;
top: 0;
bottom: 0;
color: #fff;
width: 150px;
overflow: auto;
z-index: 2;
display: flex;
flex-direction: column;
margin: 1rem 0 .5rem;
}
#phrase>div {
margin: 0 0 10px;
width: 150px;
padding: 5px 10px;
background: #007bff;
border: 2px solid #007bff;
border-radius: 6px;
color: #fff;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<h1>Drag and drop example </h1>
<button id = "add-blue-box" type = "button">Add Blue Box</button>
<div class = "wrap">
<div id = "phrase">
<div data-id = "1"><span data-id = "1" class = "words">H1 Text</span></div>
<div data-id = "2"><span data-id = "2" class = "words">H2 Text</span></div>
<div data-id = "3"><span data-id = "3" class = "words">H3 Text</span></div>
<div data-id = "4"><span data-id = "4" class = "words">H4 Text</span></div>
<div data-id = "5"><span data-id = "5" class = "words">H5 Text</span></div>
<div data-id = "6"><span data-id = "6" class = "words">H6 Text</span></div>
</div>
</div>Этот ответ о Создание элемента div в jQuery, возможно, стоит прочитать.
@Tan Ну, JQuery — это всего лишь библиотека JavaScript, поэтому должно быть много способов сделать то, что вы хотите, включая ваше предложение.
Спасибо. Итак, добавление div можно сделать и с помощью jQuery, верно? Или он упустит некоторые детали, которые вы упомянули?` let html = "<div data-id = " + i + "><span data-id = " + i + ' class = "words">' + "Ln #" + text1 + " " + text2 + "</span></div>"; $("#phrase").append(html);`