Задать вопрос
HunteR-VRX
@HunteR-VRX
Помешанный на развитии

Как реализовать display: block по событию onclick одному div и при этом всем раннее открытым из 36 штук — display: none на чистом js?

Есть 37 div'ов:
<div id="ranging_1" class="ranging_1">
  ... еще много дочерних элементов разного типа ...
</div>
<div id="ranging_2" class="ranging_2">
  ... еще много дочерних элементов разного типа ...
</div>
<div id="ranging_3" class="ranging_3">
  ... еще много дочерних элементов разного типа ...
</div>

и так далее с шагом +1 по индексам id до 37-ого включительно

Есть 37 элементов меню:
<a class="selector" href="#" onclick="openRanging_1()">Клац</a>
<a class="selector" href="#" onclick="openRanging_2()">Клац</a>
<a class="selector" href="#" onclick="openRanging_3()">Клац</a>


Все 37 div'ов предварительно скрыты средствами css, конкретнее scss препроцессором циклом @for:

@for $i from 1 through 37 {
        .ranging_#{$i} {
            display: none;
       }
}


ЗАДАЧА: По клику на конкретный элемент меню - присваивать соответствующему div - display: block, тем самым показав его и всё его содержимое, и одновременно с этим закрывать раннее открытый из возможных 36 штук div.

мой JS:
Перепробовал много вариантов, не могу достичь результата, даже не вижу смысла перечислять что именно я пробовал, скажу только то, что все 37 div'ов я получил через:
var ranging_1 = document.getElementById('ranging_1');
var ranging_1 = document.getElementById('ranging_2');
var ranging_1 = document.getElementById('ranging_3');


Далее сформировал массив из этих переменных:
var arrayRanging = [ranging_1, ranging_2, ranging_3, ranging_4, ranging_5, ranging_6, ranging_7, ranging_8, ranging_9, ranging_10, ranging_11, ranging_12, ranging_13, ranging_14, ranging_15, ranging_16, ranging_17, ranging_18, ranging_19, ranging_20, ranging_21, ranging_22, ranging_23, ranging_24, ranging_25, ranging_26, ranging_27, ranging_28, ranging_29, ranging_30, ranging_31, ranging_32, ranging_33, ranging_34, ranging_35, ranging_36, ranging_37];


И теперь я в тупике...
function openRanging_1() {
    arrayRanging[0].style.display = 'block';
        for (var i = 0; i <= arrayRanging.length; i++) {
            arrayRanging[i].style.display = 'none';
        } 
}

function openRanging_2() {
    arrayRanging[1].style.display = 'block';
        for (var i = 0; i <= arrayRanging.length; i++) {
            arrayRanging[i].style.display = 'none';
        } 
}

function openRanging_3() {
    arrayRanging[2].style.display = 'block';
        for (var i = 0; i <= arrayRanging.length; i++) {
            arrayRanging[i].style.display = 'none';
        } 
}
  • Вопрос задан
  • 2371 просмотр
Подписаться 1 Средний 5 комментариев
Решения вопроса 4
0xD34F
@0xD34F Куратор тега JavaScript
Разные классы не нужны, достаточно одного общего:

.ranging {
  display: none;
}

.ranging.opened {
  display: block;
}

При клике смотрим индекс нажатой кнопки, обходим элементы с контентом, выставляем класс в зависимости от равенства текущего индекса индексу кнопки:

const buttonSelector = '.selector';
const contentSelector = '.ranging';
const activeClass = 'opened';
const toggleContent = (contents, index) =>
  contents.forEach((n, i) => n.classList.toggle(activeClass, i === index));


// делегирование, назначаем обработчик клика один раз для всех кнопок
// наверное, у них есть какой-то общий предок, тогда вместо документа
// вешать обработчик следует на него:
// document.querySelector('селектор_контейнера_с_кнопками').addEventListener(...
document.addEventListener('click', e => {
  const button = e.target.closest(buttonSelector);
  if (button) {
    const buttons = document.querySelectorAll(buttonSelector);
    const index = Array.prototype.indexOf.call(buttons, button);
    toggleContent(document.querySelectorAll(contentSelector), index);
  }
});

// или, назначаем обработчик клика индивидуально каждой кнопке
const onClick = function(e) {
  toggleContent(this, +e.currentTarget.dataset.index);
}.bind(document.querySelectorAll(contentSelector));

document.querySelectorAll(buttonSelector).forEach((n, i) => {
  n.dataset.index = i;
  n.addEventListener('click', onClick);
});
Ответ написан
aM-aM
@aM-aM
Люблю js
Если надо без классов
<div id="ranging_1" class="ranging">
    ... еще много дочерних элементов разного типа ...
  </div>
  <div id="ranging_2" class="ranging">
    ... еще много дочерних элементов разного типа ...
  </div>
  <div id="ranging_3" class="ranging">
    ... еще много дочерних элементов разного типа ...
  </div>

  ...

  <a class="selector" href="#" data-rating-id='ranging_1'>Клац</a>
  <a class="selector" href="#" data-rating-id='ranging_2'>Клац</a>
  <a class="selector" href="#" data-rating-id='ranging_3'>Клац</a>

var rangings = [].slice.call(document.querySelectorAll('.ranging'));
var selectors = [].slice.call(document.querySelectorAll('.selector'));
selectors.forEach(function(selector) {
  selector.addEventListener('click', function(e) {
    e.preventDefault();
    var ranging = document.getElementById(e.target.dataset.ratingId);
    ranging.style.display = '';
    rangings.forEach(function(item) {
      if (item.id !== e.target.dataset.ratingId) {
        item.style.display = 'none';
      }
    })
  });
})
Ответ написан
HunteR-VRX
@HunteR-VRX Автор вопроса
Помешанный на развитии
Решил все таки самостоятельно, инструкцией которой хотел и исходя из своего положения вещей: массив / события и так далее:

function clickInfo() {
    for(var i = 0; i <= arrayRanging.length; i++) {
        arrayRanging[i].style.display = 'none';
        arrayRanging[17].style.display = 'block';
    }
}


Неработоспособность кода была выявлена, из-за присутствия атрибута для асинхронной загрузки этого скрипта:
<script src="js/open_rubrics.js" async></script>

поменял на
<script src="js/open_rubrics.js" defer></script>

Всем большое спасибо за ваши варианты!
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
devellopah
@devellopah
<div class="ranging-box">
<div id="ranging_1" class="ranging js-ranging">
  ... еще много дочерних элементов разного типа ...
</div>

<div id="ranging_1" class="ranging js-ranging d-none">
  ... еще много дочерних элементов разного типа ...
</div>

</div>

<div id="selectorList" class="selector-list">
<a class="selector js-selector-active" href="#ranging_1">Клац</a>
<a class="selector" href="#ranging_2">Клац</a>
</div>


.d-none { display: none; }

document.getElementById('selectorList').addEventListener('click', function(e) {
    if(e.target.nodeType === "A") {
        var activeSelector = document.querySelector('.js-selector-active');
        document.getElementById(e.target.href).className -= " d-none";
        document.getElementById(activeSelector.href).className += " d-none";
        activeSelector.className -= " js-selector-active";
        e.target.className += " js-active-selector";
    }
})


p.s. примерно как-то так, возможно где-то ошибся в синтаксисе, писал сходу и в спешке.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы