css селектор: последний ребенок и: не - PullRequest
0 голосов
/ 17 февраля 2019

Я надеюсь использовать селекторы CSS, чтобы выбрать последний файл в последнем не скрытом каталоге, который является 6, со следующим кодом Javascript:

const root = document.querySelector('#root');
const last = root.querySelector('.dir:not(.hidden):last-child .file:last-child');
console.log(last.innerHTML);

Но результат 3.Интересно, есть ли способ получить 6 только с помощью селекторов CSS, в отличие от рекурсивного кода Javascript.

HTML:

<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='dir hidden'>
        <div class='dir'>
          <div class='file'>7</div>
          <div class='file'>8</div>
          <div class='file'>9</div>
        </div>
      </div>
    </div>
  </div>
</div>

https://jsbin.com/moyagivopi/1/edit?html,js,console

https://jsbin.com/huteqabiga/1/edit?html,js,console

https://jsbin.com/vosereyime/1/edit?html,js,console

Ответы [ 3 ]

0 голосов
/ 17 февраля 2019

Вы можете использовать querySelectorAll, а затем нарезать, чтобы получить последний элемент в массиве.

См. Ниже.

const root = document.querySelector('#root');
const last = Array.prototype.slice.call(root.querySelectorAll('.dir:not(.hidden):first-child > .file:last-child')).slice(-1)[0];
console.log(last.innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir hidden'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>
0 голосов
/ 17 февраля 2019

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

Для справки: https://codeburst.io/learn-and-understand-recursion-in-javascript-b588218e87ea

const root = document.querySelector('#root');
const files = root.querySelectorAll('.file');
var div;

for (var i=0; i< files.length; i++){
  if (!doesParentContainClass(files[i])) {
    div = files[i]; 
  }
}

console.log(div.innerHTML)

function doesParentContainClass(element) {
    if (element.className && element.className.split(' ').indexOf('hidden')>=0) return true;
    return element.parentNode && doesParentContainClass(element.parentNode);
}
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir hidden'>
    <div class='dir'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>

const root = document.querySelector('#root');
const files = root.querySelectorAll('.file');
var div;

for (var i=0; i< files.length; i++){
  if (!doesParentContainClass(files[i])) {
    div = files[i]; 
  }
}

console.log(div.innerHTML)

function doesParentContainClass(element) {
    if (element.className && element.className.split(' ').indexOf('hidden')>=0) return true;
    return element.parentNode && doesParentContainClass(element.parentNode);
}
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='dir hidden'>
        <div class='dir'>
          <div class='file'>7</div>
          <div class='file'>8</div>
          <div class='file'>9</div>
        </div>
      </div>
    </div>
  </div>
</div>
0 голосов
/ 17 февраля 2019

Вы можете разделить ваш выбор в 2 шага, сначала вы получаете элементы без .hidden, затем вы выбираете последний внутри последний .Я не думаю, что у вас будет шанс с чистым CSS

var last = document.querySelectorAll('#root > .dir:not(.hidden) > .dir:not(.hidden)');

var element = last[last.length - 1].querySelector('.file:last-child');

console.log(element.innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir hidden'>
    <div class='dir'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>

Другой пример:

var last = document.querySelectorAll('#root > .dir:not(.hidden) > .dir:not(.hidden)');

var element = last[last.length - 1].querySelector('.file:last-child');

console.log(element.innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir hidden'>
      <div class='file'>7</div>
      <div class='file'>8</div>
      <div class='file'>9</div>
    </div>
  </div>
</div>

Другая идея состоит в том, чтобы выбрать все последние .file, а затем запустить тест из последнего, чтобы увидеть, есть ли предок с классом .hidden,В отличие от предыдущего решения это будет работать с любым уровнем вложенности.

//got from this answer https://stackoverflow.com/a/16863971/8620333
function hasSomeParentTheClass(element, classname) {
  if (element.classList.contains(classname)) return true;
  return element.parentElement && hasSomeParentTheClass(element.parentElement, classname);
}

var elements = document.querySelectorAll('.file');
var i = elements.length - 1;
for (; i >= 0; i--) {
  if (!hasSomeParentTheClass(elements[i], 'hidden')) {
    break;
  }
}

console.log(elements[i].innerHTML);
<div id='root'>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>1</div>
      <div class='file'>2</div>
      <div class='file'>3</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir'>
      <div class='file'>4</div>
      <div class='file'>5</div>
      <div class='file'>6</div>
    </div>
  </div>
  <div class='dir'>
    <div class='dir '>
    <div class='file'>10</div>
      <div class='dir hidden'>
        <div class='file'>7</div>
        <div class='file'>8</div>
        <div class='file'>9</div>
      </div>
    </div>
  </div>
</div>

Отредактировано OP: удалено :last-child, если файл 10 существует.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...