Форум программистов, компьютерный форум, киберфорум
JavaScript для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
1 / 1 / 0
Регистрация: 19.04.2021
Сообщений: 44
1

Элементы возвращаются неправильно

12.07.2023, 20:11. Показов 802. Ответов 18
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Мне нужна ваша помощь. Моя задача состоит в том, чтобы создать 100 div с помощью чистого JavaScript. Каждый div должен обладать следующей функциональностью: Каждый div имеет свое название, типа div1, div2, div3 и до 100. Предположим, зову я на 31, 45, 89, они перемещаюсь наверх. Теперь элементы у меня становятся

div89, div45, div31, div1, div2

и на месте тех, которые я забрал, идут:

div30 - div32 - div33,
div43 -div44 - div46
div88 – div90 – div91

Когда я щелкаю еще раз на поднявшиеся наверх элементы, они должны вернуться на предыдущие позиции.

Проблема заключается в том, что они возвращаюсь назад, но в произвольные места списка (иногда нормально, иногда нет) и список у меня не выглядит поочередно. Где моя ошибка? Спасибо вам большое

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
document.addEventListener('DOMContentLoaded', function() {
    for (let i = 1; i <= 100; i++) {
        const div = document.createElement('div');
        div.className = 'div-element';
        div.textContent = 'div' + i;
        document.body.appendChild(div);
    }
 
    const originalPositions = Array.from(document.getElementsByClassName('div-element')).map((div, index) => index);
 
    const divElements = document.getElementsByClassName('div-element');
    for (let i = 0; i < divElements.length; i++) {
        const div = divElements[i];
        let isFirstPosition = false;
        let originalPosition = -1;
 
        div.addEventListener('click', function() {
            if (!isFirstPosition) {
                document.body.insertBefore(div, document.body.firstElementChild);
                isFirstPosition = true;
                originalPosition = i;
            } else {
                const referenceDiv = divElements[originalPositions[originalPosition]];
                document.body.insertBefore(div, referenceDiv.nextElementSibling);
                isFirstPosition = false;
            }
        });
    }
});
1
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.07.2023, 20:11
Ответы с готовыми решениями:

ASP.Core: не возвращаются элементы getElementsByClassName() == [0]
В отладчике VS для JavaScript не возвращается ни один элемент по функции getElementsByClassName(),...

Элементы неправильно заносятся в список
#include &lt;iostream&gt; #include &lt;string&gt; #include &lt;fstream&gt; using namespace std; struct word...

Неправильно меняет элементы на нули
#include &lt;iostream.h&gt; #include &lt;iomanip.h&gt; #include &lt;conio.h&gt; using namespace std; int main...

Неправильно удаляются элементы стека
Вопрос в теме. Делаю на Visual Studio Не могу понять в чем дело Вводит нормально (число элем=3)...

функция неправильно считает элементы
Здравствуйте. Есть функция, которая ведет подсчет количества правильно выбранных radio в тесте. ...

18
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,046
Записей в блоге: 12
12.07.2023, 22:06 2
Потому что ты работаешь с индексами массива

Пример
1 2 3 4 5 6
допустим мы переместили вперед 6 5 4, т.е. сначала 6 потом 5 потом 4
4 5 6 1 2 3

Для красоты демонстрации я считаю позиции/индекс элемента в массиве originalPositions не снуля как у тебя в коде а с 1, т.е. во второй строке это позиция а в первой значение
6 вернули на место
4 5 1 2 3 6 - значения
1 2 3 4 5 6 - индексы
4 вернули
5 1 2 4 3 6 - значения
1 2 3 4 5 6 - индексы
5 вернули
1 2 4 3 5 6 - значения
1 2 3 4 5 6 - индексы

итого после всех возвратов получили 1 2 4 3 5 6 вместо 1 2 3 4 5 6
нужно перемещать элементы сравнивая значения, а не инндексы, ты только что продемострировал проблемы которую решает key в react
1
1 / 1 / 0
Регистрация: 19.04.2021
Сообщений: 44
12.07.2023, 22:24  [ТС] 3
Спасибо большое, однако я это задача для чистого js. Можете помочь мне это исправить? Буду очень благодарен
0
3498 / 1262 / 428
Регистрация: 24.07.2016
Сообщений: 1,888
13.07.2023, 00:36 4
Цитата Сообщение от Halland Посмотреть сообщение
это задача для чистого js
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const container = document.body.appendChild(document.createElement('div'));
 
[...Array(100).keys()].forEach(i => {
    let div = container.appendChild(document.createElement('div'));
    
    div.classList.add('div-element');
    div.textContent = `div_${++i}`;
    
    Object.assign(div.style, {
        cursor: 'pointer',
        margin: '5px 0',
        padding: '3px',
        textAlign: 'center',
        border: '1px solid green',
        borderRadius: '4px',
        boxSizing: 'border-box',
        backgroundColor: '#D8D8B1'
    });
});
 
container.addEventListener(
    'click',
    e => e.target.classList.contains('div-element') ? container.prepend(e.target) : null
);
Добавлено через 3 минуты
Цитата Сообщение от Halland Посмотреть сообщение
Когда я щелкаю еще раз на поднявшиеся наверх элементы, они должны вернуться на предыдущие позиции.
До этого я ещё не дочитал...
0
3498 / 1262 / 428
Регистрация: 24.07.2016
Сообщений: 1,888
13.07.2023, 20:50 5
Дочитал...
Halland, задача в таком виде нерешаема, т.к. нет критерия очерёдности повторных кликов. Вот эта твоя фраза...
Цитата Сообщение от Halland Посмотреть сообщение
Когда я щелкаю еще раз на поднявшиеся наверх элементы, они должны вернуться на предыдущие позиции.
Замечательно. Теперь давай определись, где эта предыдущая позиция? Какбэ всё говорит о том, что это его стартовая, индексная позиция в коллекции. Допустим поставили элемент на своё место. А если ты нащёлкал перед этим кучу других элементов в рандомном порядке и они поднялись наверх, то при повторном клике они сдвинут элемент, ранее поставленный на место, и он в итоге окажется не на своём месте.

Если тебя устроит вот такое, то держи ... поклацай, подумай
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const container = document.body.appendChild(document.createElement('div'));
const getElems = box => [...box.querySelectorAll('*')];
 
[...Array(100).keys()].forEach(i => {
    let div = container.appendChild(document.createElement('div'));
    
    div.classList.add('div-element');
    div.dataset.index = i;
    div.textContent = `div${++i}`;
    
    Object.assign(div.style, {
        cursor: 'pointer',
        margin: '5px 0',
        padding: '3px',
        textAlign: 'center',
        border: '1px solid green',
        borderRadius: '4px',
        boxSizing: 'border-box',
        backgroundColor: '#D8D8B1'
    });
});
 
container.addEventListener('click', function (e) {
    if(!e.target.classList.contains('div-element')) return;
    
    if(e.target.classList.contains('off')) {
        getElems(this).find((_, i) => e.target.dataset.index == i).insertAdjacentElement(
            'afterEnd',
            e.target
        );
    } else {
        this.prepend(e.target);
    }
    
    e.target.classList.toggle('off');
});
0
89 / 74 / 24
Регистрация: 16.05.2023
Сообщений: 268
13.07.2023, 23:16 6
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Создаем 100 div элементов с уникальными именами
var container = document.getElementById("container");
for (var i = 1; i <= 100; i++) {
    var div = document.createElement("div");
    div.classList.add("box");
    div.id = "div" + i;
    div.innerHTML = "div" + i;
    container.appendChild(div);
}
 
// Функция перемещения выбранного элемента наверх или вниз
function moveElement(element) {
    var originalPos;
  
    // Если элемент уже был выбран
    if (element.classList.contains("selected")) {
        // Возвращаем его на оригинальное место
        originalPos = element.dataset.originalPos;
        container.insertBefore(element, container.children[parseInt(originalPos) + 1]);
        element.classList.remove("selected");
    } else {
        // Добавляем элемент наверх
        originalPos = Array.from(container.children).indexOf(element);
        element.dataset.originalPos = originalPos;
        container.insertBefore(element, container.firstChild);
        element.classList.add("selected");
    }
}
 
// Добавляем обработчики событий клика на каждый div элемент
var divs = document.querySelectorAll(".box");
divs.forEach(function(div) {
    div.addEventListener("click", function() {
        moveElement(div);
    });
});
Добавлено через 1 минуту
HTML5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
    <title>Divs</title>
    <style>
        .box {
            width: 100px;
            height: 100px;
            margin: 10px;
            background-color: #ccc;
            display: inline-block;
            text-align: center;
            line-height: 100px;
            font-size: 20px;
        }
    </style>
</head>
<body>
    <div id="container"></div>
</body>
</html>
Добавлено через 1 минуту
Суть в том, что при первом клике идёт запись в атрибут оригинальной позиции, и добавляется класс selected (можно и без него). А при повторном клике, идёт перемещение на обратную позицию из атрибута.

Ничего сложного

Добавлено через 4 минуты
А я понял в чём проблема
0
3498 / 1262 / 428
Регистрация: 24.07.2016
Сообщений: 1,888
13.07.2023, 23:53 7
Цитата Сообщение от mr_dramm Посмотреть сообщение
нужно перемещать элементы сравнивая значения, а не инндексы
Это тот же хрен, только тень слева и задачу не решит.
0
89 / 74 / 24
Регистрация: 16.05.2023
Сообщений: 268
13.07.2023, 23:58 8
Цитата Сообщение от klyapa Посмотреть сообщение
Это тот же хрен, только тень слева и задачу не решит.
Проблема задачи состоит в том, что при выборе несколько значений. Остальные div сдвинулись. И ранее записанная индексация, уже не будет верна по отношению к другим. Неважно каким образом была записана другая позиция.
0
3498 / 1262 / 428
Регистрация: 24.07.2016
Сообщений: 1,888
14.07.2023, 00:36 9
Цитата Сообщение от Hmms Посмотреть сообщение
Ничего сложного
угу
Цитата Сообщение от Hmms Посмотреть сообщение
А я понял в чём проблема
уже лучше
Цитата Сообщение от Hmms Посмотреть сообщение
Проблема задачи состоит в том, что при выборе несколько значений. Остальные div сдвинулись. И ранее записанная индексация, уже не будет верна по отношению к другим. Неважно каким образом была записана другая позиция.
да ... причём, если искать элементы по значению, чтобы правильно вставить event.target, то тоже получим баг, только с другим алгоритмом, нежели баг с индексами
0
89 / 74 / 24
Регистрация: 16.05.2023
Сообщений: 268
14.07.2023, 00:45 10
Можно немного по другому решить задачу, всё таки сделать начальную метку. А потом бегать, и искать от куда родом данный div

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Создаем 100 div элементов с уникальными именами
var container = document.getElementById("container");
for (var i = 1; i <= 100; i++) {
    var div = document.createElement("div");
    div.classList.add("box");
    div.id = "div" + i;
    div.innerHTML = "div" + i;
    div.dataset.originalPos = i - 1;
    container.appendChild(div);
}
 
// Функция перемещения выбранного элемента наверх или вниз
function moveElement(element) {
   if (element.classList.contains("selected")) {
      let originalPos = parseInt(element.dataset.originalPos);
      let MoveIndex = container.children.length;
     
      for (let i = 0; i < MoveIndex; i++) {
        let currentDiv = container.children[i];
         if(!currentDiv.classList.contains("selected")
            && originalPos <= parseInt(currentDiv.dataset.originalPos)) {
            MoveIndex = i;
           break;
          } 
      }
       container.insertBefore(element, container.children[MoveIndex]); 
       element.classList.remove("selected");
   } else {
        container.insertBefore(element, container.firstChild);
        element.classList.add("selected");
   }
}
 
// Добавляем обработчики событий клика на каждый div элемент
var divs = document.querySelectorAll(".box");
divs.forEach(function(div) {
    div.addEventListener("click", function() {
        moveElement(div);
    });
});
Этот код решает проблему
1
3498 / 1262 / 428
Регистрация: 24.07.2016
Сообщений: 1,888
14.07.2023, 01:48 11
Цитата Сообщение от Hmms Посмотреть сообщение
Можно немного по другому решить задачу
ну да, по-другому можно...
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const box = document.body.appendChild(document.createElement('div'));
 
[...Array(100).keys()].forEach(i => {
    let div = box.appendChild(document.createElement('div'));
    div.classList.add('div-element');
    div.dataset.sel = i;
    div.textContent = `div${++i}`;
    
    Object.assign(div.style, {
        cursor: 'pointer',
        margin: '5px 0',
        padding: '3px',
        textAlign: 'center',
        border: '1px solid green',
        borderRadius: '4px',
        boxSizing: 'border-box',
        backgroundColor: '#D8D8B1'
    });
});
 
box.addEventListener('click', function (e) {
    if(!e.target.classList.contains('div-element')) return;
    if(e.target.classList.contains('off')) {
        this.querySelector(`[data-mark="${e.target.dataset.sel}"]`).replaceWith(e.target);
    } else {
        let s = document.createElement('span');
        s.dataset.mark = e.target.dataset.sel;
        e.target.after(s);
        this.prepend(e.target);
    }
    e.target.classList.toggle('off');
});
1
89 / 74 / 24
Регистрация: 16.05.2023
Сообщений: 268
14.07.2023, 02:46 12
Цитата Сообщение от klyapa Посмотреть сообщение
ну да, по-другому можно...
Да, тоже неплохой вариант, создать span невидимый. И потом возвращать оригинальную тушку на место его
0
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,046
Записей в блоге: 12
14.07.2023, 11:33 13
Цитата Сообщение от klyapa Посмотреть сообщение
Это тот же хрен, только тень слева и задачу не решит.
я уверен что этот "хрен" должен справиться, так, как если бы проверялись значения, а именно последовательность цифр в div.innerText, которая по условию должна быть отсортирована по возрастанию, и таким образом ты не вставишь 4 перед 3, если правильно напишешь проход(поиск места вставки) и вставку. Сложность задачи от O(1) до O(logN), можно считать число перемещенных элементов в начало списка, тогда оставшиеся это отсортированный массив с пропусками, в котором для поиска места вставки предлагаю использовать используем бинарный поиск.
0
3498 / 1262 / 428
Регистрация: 24.07.2016
Сообщений: 1,888
15.07.2023, 01:07 14
Цитата Сообщение от mr_dramm Посмотреть сообщение
я уверен что этот "хрен" должен справиться, так, как если бы проверялись значения, а именно последовательность цифр в div.innerText
Пример с innerText (значение)
Код
1 2 3 4 5 6
допустим мы переместили вперед 2 3 4, т.е. сначала 2 потом 3 потом 4
имеем на выхлопе...
Код
4 3 2 1 5 6
Теперь перемещаем обратно. Для "красоты демонстрации"* перемещаем текущий элемент за меньшую цифру (на 1)
То есть, жмём на 3 и элемент перемещается под двойку... У нас ведь нет чёткого критерия последовательности, какой элемент возвращать на место, так что рандомно жмём тройку...
Код
4 2 3 1 5 6
Дальше двойку клацаем ... перемещается под единицу
Код
4 3 1 2 5 6
Остаётся четвёрка, которая переместится под тройку. И что имеем? А имеем тот самый "хрен", о котором упомянул выше
Код
3 4 1 2 5 6
1
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,046
Записей в блоге: 12
15.07.2023, 01:53 15
Цитата Сообщение от klyapa Посмотреть сообщение
Теперь перемещаем обратно. Для "красоты демонстрации"* перемещаем текущий элемент за меньшую цифру (на 1)
То есть, жмём на 3 и элемент перемещается под двойку... У нас ведь нет чёткого критерия последовательности, какой элемент возвращать на место, так что рандомно жмём тройку...
klyapa, спасибо тебе за ответ, я извиняюсь за неясное толкование своего решения попробую объяснить, правильная последовательность после клику по 3 будет

4 2 1 3 5 6

Цитата Сообщение от mr_dramm Посмотреть сообщение
Сложность задачи от O(1) до O(logN), можно считать число перемещенных элементов в начало списка, тогда оставшиеся это отсортированный массив с пропусками, в котором для поиска места вставки предлагаю использовать используем бинарный поиск.
"можно" лучше заменить на "нужно", т.е. место вставки будет только в тот набор который не участвовал в перемещении(оставшиеся это отсортированный массив), т.е. первая цифра, которая не перемещалась в данном случае 1, и с нее начнется поиск места вставки.

после этого у нас будет снова два массива, массивы условно разделены пременной счетчиком который будет равен 2 (до клика по 3 был равен 3), на самом деле это один массив точнее HTMLCollection

4 2(отсюда можно брать и сюда можно перемещать новые элементы) и 1 3 5 6 (тут ищем место вставки и вставляем)
0
89 / 74 / 24
Регистрация: 16.05.2023
Сообщений: 268
15.07.2023, 11:01 16
Цитата Сообщение от mr_dramm Посмотреть сообщение
"можно" лучше заменить на "нужно", т.е. место вставки будет только в тот набор который не участвовал в перемещении(оставшиеся это отсортированный массив), т.е. первая цифра, которая не перемещалась в данном случае 1, и с нее начнется поиск места вставки.

Более правильная реализация, с данным алгоритмом

PHP
1
2
3
4
5
6
7
8
    for (let i = 0; i < MoveIndex; i++) {
        let currentDiv = container.children[i];
         if(!currentDiv.classList.contains("selected")
            && originalPos <= parseInt(currentDiv.dataset.originalPos)) {
            MoveIndex = i;
           break;
          } 
      }
Только мы определяем, что у нас нету класса selected.
0
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,046
Записей в блоге: 12
15.07.2023, 12:59 17
не хочу спорить на счет правильно не правильно, просто потому что кто - то это сказал...
у тебя тоже есть подсчет перемещенных/выбранных(selected) элементов, только другим способом...
0
89 / 74 / 24
Регистрация: 16.05.2023
Сообщений: 268
15.07.2023, 15:47 18
Цитата Сообщение от mr_dramm Посмотреть сообщение
не хочу спорить на счет правильно не правильно
Я написал что - более правильная.

Цитата Сообщение от mr_dramm Посмотреть сообщение
просто потому что кто - то это сказал...
Логика сказала -

Данный код отлично решает задачу перемещения выбранного элемента наверх или вниз. В данном случае, код использует цикл for, чтобы найти правильное место для перемещения выбранного элемента.

В цикле проходится по каждому дочернему элементу контейнера и проверяет условие: если текущий элемент не содержит класс "selected" (то есть не является выбранным) и его оригинальная позиция (originalPos) больше или равна оригинальной позиции выбранного элемента, то запоминается индекс этого элемента в переменную MoveIndex.

После завершения цикла, выбранный элемент перемещается перед элементом с индексом MoveIndex с помощью container.insertBefore(). Затем выбранный элементу удаляется класс "selected", чтобы он больше не считался выбранным.

Если элемент не является выбранным, то он просто перемещается в начало контейнера с помощью container.insertBefore() и добавляется класс "selected".

Таким образом, этот код эффективно перемещает выбранный элемент наверх или вниз, основываясь на его оригинальной позиции и манипулируя DOM.


Цитата Сообщение от mr_dramm Посмотреть сообщение
только другим способом...
Приведи рабочий пример и ты
0
молодой
1769 / 1010 / 320
Регистрация: 17.07.2021
Сообщений: 2,046
Записей в блоге: 12
18.07.2023, 13:28 19
я придумал альтернативное решение
PHP/HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<!DOCTYPE html>
<html>
 
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title></title>
    <style>
    .box {
        display: flex;
        justify-content: center;
        gap: .5rem;
    }
 
    .item {
        padding: 1rem;
        border: 1px black solid;
        cursor: pointer;
        user-select: none;
    }
 
    .item[style] {
        background: orange;
 
    }
    </style>
</head>
 
<body>
    <div class="box">
    </div>
    <script>
    const box = document.querySelector(".box");
    for (let i = 1; i <= 10; i++) {
        const div = document.createElement('div');
        div.className = 'item';
        div.textContent = i;
        document.querySelector(".box").appendChild(div);
    }
    let counter = 0;
    box.addEventListener("click", (e) => {
        const t = e.target
        if(!t.classList.contains("item")) return;
        if(t.hasAttribute("style")){
            t.removeAttribute("style")
        }
        else{
            t.style.order = --counter
        }
    })
    </script>
</body>
 
</html>
0
18.07.2023, 13:28
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.07.2023, 13:28
Помогаю со студенческими работами здесь

Неправильно считает элементы матрицы
u=*k w=*k c=sqrt((a)) for j in range(1,k): c=a/c for k in range(0, (j-1)): ...

Консоль неправильно выводит элементы массива
Добрый вечер, нужна помощь. Задача в приложении Составил список, однако при его выводе выдает...

Неправильно выводит элементы массива в textbox
Здравствуйте, у меня возникла проблема при выводе элементов одномерного массива на textbox, он...

Неправильно выводит на экран элементы структуры
Здравствуйте! Суть вопроса (код полностью прикрепила файлом): typedef struct Data{ char name;...

Отладчик отображает поля структур и элементы массивов неправильно
Доброго времени суток! При отладке приложения на С++ столкнулся со следующей проблемой -...

Не возвращаются фото из БД
Всем привет. Использую оч странную связку Postgress + Dapper + Asp.net core mvc(такое тз просто)....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru