Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Найти определённого, наважно какого юродного, брата (https://javascript.ru/forum/dom-window/49221-najjti-opredeljonnogo-navazhno-kakogo-yurodnogo-brata.html)

sergej_savelev 03.08.2014 15:18

Найти определённого, наважно какого юродного, брата
 
Например, имея структуру:
<div>
	<h1>title</h1>
</div>
<h2>title</h2>

Или:
<div>
	<h1>title</h1>
</div>
<div>
	<h2>title</h2>
</div>

Или:
<h1>title</h1>
<div>
	<h2>title</h2>
</div>

Или:
<h1>title</h1>
<h2>title</h2>

Или же:
<div>
	<h1>title</h1>
</div>
<div>
	<h1>title</h1>
</div>
<div>
	<h2>title</h2>
</div>

Как одной универсальной строкой jQuery или javascript, найти определённый первый попавшийся предыдущий элемент, относительно выбранного селектора. Например, было бы логично что-то типа:
$('h2').prevAll('h1:first')

Но, увы для меня, данная строка действует лишь для 4 примера и подобных ему, во всех остальных случая нужно выдумывать что-то своё, при этом, мне, не удаётся найти конкретно первого перед выбранным, например в такой структуре:
<div>
	<h1>title</h1>
	<h1>title</h1>
</div>
<div>
	<h1>title</h1>
	<h1>title</h1>
</div>
<div>
	<h1>title</h1>
</div>
<div>
	<h2>title</h2>
</div>

Так как нужно что-то типа:
$('h2').parents().find('h1:last:first')

Не уверен, что это будет работать, хотя стоит проверить..., но всё же хочется знать, нет ли универсальной функции для поиска подобных элементов?

melky 03.08.2014 15:23

Цитата:

Сообщение от sergej_savelev
Найти определённого, наважно какого юродного, брата


sergej_savelev 03.08.2014 15:24

Удивительно, но мой пример, вроде бы, как раз то самое универсальное решение :)

sergej_savelev 03.08.2014 15:25

http://jsfiddle.net/2vsB6/

sergej_savelev 03.08.2014 15:26

Да, наважно кокого)))

sergej_savelev 03.08.2014 15:30

Хотя, всё же, нет, это не то - http://jsfiddle.net/2vsB6/2/

sergej_savelev 03.08.2014 15:31

Нужен именно предыдущий, в моём же решении может найтись элемент который за тем от которого происходит поиск.

sergej_savelev 03.08.2014 15:33

Пожалуйста, не нужно шутить, реально нужен дельный совет ;)

melky 03.08.2014 15:40

Цитата:

Сообщение от sergej_savelev (Сообщение 324071)
Пожалуйста, не нужно шутить, реально нужен дельный совет ;)

если нормально опишешь, в чём дело, то я попробую тебе помочь.. а так - я нифига не понял

sergej_savelev 03.08.2014 15:52

1
2
3
4
5
6

Из этих чисел выберем 6, число 5 будет перед ним.

1
3
2
4
6
5

В данном случае перед 6 будет элемент 4.

Это, значит, получение первого элемента, стоящего впереди выбранного.

В структуре HTML не всё так просто, элементы разбросаны по веткам и нужный элемент в таком случае может оказать очень далеко, но всё же в DOM он будет перед выбранным. Так вот как его определить? Не запутал ещё сильней? :)

melky 03.08.2014 16:17

http://jsbin.com/juqenojo/1

оно?

твои варианты чутка другие :

http://jsbin.com/ledexusa/1

$('h2').each(function (i) {
  
  $(this).
    css('color', 'red').
    text('h2: ' + i).
  
      parents(':first').andSelf().
  
      prev('h1, *:has(h1)').
  
          text('h1: ' + i).
          css('color', 'blue');
  
});

sergej_savelev 03.08.2014 19:05

Странно, вроде бы как работает, но я не могу понять как. Что делает andSelf()? Вроде бы кода раз два и обчёлся а в голове хаос, неразбериха... Ещё не могу понять как :has() работает, даже догадаться не получается.

sergej_savelev 03.08.2014 19:06

Дома жара, весь мокрый, не могу думать.

sergej_savelev 03.08.2014 19:14

Поеду прокачусь на доске лучше. Спасибо!

melky 03.08.2014 19:17

Цитата:

Сообщение от sergej_savelev (Сообщение 324096)
Странно, вроде бы как работает, но я не могу понять как. Что делает andSelf()? Вроде бы кода раз два и обчёлся а в голове хаос, неразбериха... Ещё не могу понять как :has() работает, даже догадаться не получается.

точнее, даже так:
$('h2').each(function (i) {
  
  $(this).
    css('color', 'red').
    text('h2: ' + i).
  
      parents('div:last').andSelf().
  
        prev('h1, div:has(h1)').
  
          text('h1: ' + i).
          css('color', 'blue');
  
});




теперь поясню:

$('h2').each(function (i) {
  
  $(this).
    css('color', 'red').
    text('h2: ' + i).
  
*!*
      parents('div:last').andSelf().
*/!*
  
        prev('h1, div:has(h1)').
  
          text('h1: ' + i).
          css('color', 'blue');
  
});


Эта строчка найдёт DIV на самом верхнем уровне вложенности, считая от h2... (это не всё)

выделен жёлтым:

вот:

ещё:


и поместит в список к найденному элементу и сам элемент h2 (andSelf).

....
Далее,


$('h2').each(function (i) {
  
  $(this).
    css('color', 'red').
    text('h2: ' + i).
  

      parents('div:last').andSelf().

 *!* 
        prev('h1, div:has(h1)').
 */!*
 
          text('h1: ' + i).
          css('color', 'blue');
  
});


Пройдётся по элементам предыдущей выборки (div на верхнем уровне, или сам h2) и найдёт предыдущий h1, или div, внутри которого есть h1

в инете есть документация по селектору has, и по всем методам ...

Aetae 03.08.2014 21:02

Нафиг это ваше jquery.
<div>
    <h1>title</h1>
</div>
<h2>title</h2>
<script>
var nodes = document.getElementsByTagName('*'), i = nodes.length;
var el = document.querySelector('h2'), findTag = 'H1';
while(i--) if(nodes[i] === el) break;
while(i--) if(nodes[i].tagName === findTag) break; 
if(nodes[i]) nodes[i].style.color='#f00';
</script>
<div>
    <h1>title</h1>
</div>
<div>
    <h2>title</h2>
</div>
<script>
var nodes = document.getElementsByTagName('*'), i = nodes.length;
var el = document.querySelector('h2'), findTag = 'H1';
while(i--) if(nodes[i] === el) break;
while(i--) if(nodes[i].tagName === findTag) break; 
if(nodes[i]) nodes[i].style.color='#f00';
</script>
<h1>title</h1>
<div>
    <h2>title</h2>
</div>
<script>
var nodes = document.getElementsByTagName('*'), i = nodes.length;
var el = document.querySelector('h2'), findTag = 'H1';
while(i--) if(nodes[i] === el) break;
while(i--) if(nodes[i].tagName === findTag) break; 
if(nodes[i]) nodes[i].style.color='#f00';
</script>
<h1>title</h1>
<h2>title</h2>
<script>
var nodes = document.getElementsByTagName('*'), i = nodes.length;
var el = document.querySelector('h2'), findTag = 'H1';
while(i--) if(nodes[i] === el) break;
while(i--) if(nodes[i].tagName === findTag) break; 
if(nodes[i]) nodes[i].style.color='#f00';
</script>
<div>
    <h1>title</h1>
</div>
<div>
    <h1>title</h1>
</div>
<div>
    <h2>title</h2>
</div>
<script>
var nodes = document.getElementsByTagName('*'), i = nodes.length;
var el = document.querySelector('h2'), findTag = 'H1';
while(i--) if(nodes[i] === el) break;
while(i--) if(nodes[i].tagName === findTag) break; 
if(nodes[i]) nodes[i].style.color='#f00';
</script>
<div>
    <h1>title</h1>
    <h1>title</h1>
</div>
<div>
    <h1>title</h1>
    <h1>title</h1>
</div>
<div>
    <h1>title</h1>
</div>
<div>
    <h2>title</h2>
</div>
<script>
var nodes = document.getElementsByTagName('*'), i = nodes.length;
var el = document.querySelector('h2'), findTag = 'H1';
while(i--) if(nodes[i] === el) break;
while(i--) if(nodes[i].tagName === findTag) break; 
if(nodes[i]) nodes[i].style.color='#f00';
</script>

sergej_savelev 04.08.2014 12:19

Цитата:

Сообщение от Aetae
Нафиг это ваше jquery.

Думаю, с ним было бы быстрей и приятней для глаз, нет? Или ты скажешь, что может быть приятней чистого кода и что быстрей написать свою функцию чем искать плагин (не буду упомянать чего). Вообще я с тобой согласен, очень рад что есть такие грамотные люди как ты. А как звучит-то
Цитата:

Сообщение от Aetae
Нафиг это ваше jquery.

Ведь MELKY не плох, но фраза зачёт :)

sergej_savelev 04.08.2014 12:41

Жаль что я не могу внедрить ни первый ни второй пример в свой код. И так и эдак пытаюсь, но не получается.

sergej_savelev 04.08.2014 12:46

var lengthH2 = $('#contentInner h2').length;
    
    if(lengthH2>0){
        
        $('<ul></ul>').appendTo('#indexMenu>ul>li');
        
        for(i=0;i<lengthH2;i++){
            
            var nodes = document.getElementsByTagName('*'), i = nodes.length;
            var el = document.querySelector('h2'), findTag = 'H1';
            while(i--) if(nodes[i] === el) break;
            while(i--) if(nodes[i].tagName === findTag) break;
            if(nodes[i]) var parentClass = nodes[i].className;
            
            //var parentClass = $('#contentInner h2').eq(i).parents().prev('h1, :has(h1):first').attr('class');
                
            if($('#contentInner h2:not(#pagetitle)').eq(i).text().length>50){
                
                var text = '<li class="h2-'+i+'"><a href="[[~[[*id]]]]#h2-'+i+'" title="'+$('#contentInner h2:not(#pagetitle)').eq(i).text().replace(/^\s*|\s+$/g, '').replace(/\t|\n/g, ' ')+'">'+$.trim($('#contentInner h2:not(#pagetitle)').eq(i).text().slice( 0, 50 )) + '…'+'</a></li>'
                
            }else{
                
                var text = '<li class="h2-'+i+'"><a href="[[~[[*id]]]]#h2-'+i+'">'+$('#contentInner h2:not(#pagetitle)').eq(i).text().replace(/^\s*|\s+$/g, '').replace(/\t|\n/g, ' ')+'</a></li>'
                
            }
            
            $('#contentInner h2').eq(i).addClass('h2-'+i) // .append('<a name="h2-'+i+'"></a>');
            
            $(text).appendTo('#indexMenu>ul>li.'+parentClass+'>ul');
            
        }
        
    }

Почему-то в if(nodes[i]) var parentClass = nodes[i].className; всего один раз получает класс.

sergej_savelev 04.08.2014 14:14

Никогда не работал с Vanilla JS)

sergej_savelev 04.08.2014 14:21

var H2 = $('#contentInner h2');
    
    if(H2.length>0){
        
        $('<ul></ul>').appendTo('#indexMenu>ul>li');
        
        for(i=0;i<H2.length;i++){
        
            var sh1 = null, sh2 = H2[i], f = false;
            
            $('#contentInner h1, #contentInner h2').each(function(ind,o){
                if ( f ) return;
                if ( o.nodeName.toLowerCase() == 'h1' ){
                    sh1 = o;
                    return;
                }
                if ( o === sh2 ){
                    f = true;
                }
            });
            
            var parentClass = sh1.className;
            
                
            if($('#contentInner h2:not(#pagetitle)').eq(i).text().length>50){
                
                var text = '<li class="h2-'+i+'"><a href="[[~[[*id]]]]#h2-'+i+'" title="'+$('#contentInner h2:not(#pagetitle)').eq(i).text().replace(/^\s*|\s+$/g, '').replace(/\t|\n/g, ' ')+'">'+$.trim($('#contentInner h2:not(#pagetitle)').eq(i).text().slice( 0, 50 )) + '…'+'</a></li>'
                
            }else{
                
                var text = '<li class="h2-'+i+'"><a href="[[~[[*id]]]]#h2-'+i+'">'+$('#contentInner h2:not(#pagetitle)').eq(i).text().replace(/^\s*|\s+$/g, '').replace(/\t|\n/g, ' ')+'</a></li>'
                
            }
            
            $('#contentInner h2').eq(i).addClass('h2-'+i) // .append('<a name="h2-'+i+'"></a>');
            
            $(text).appendTo('#indexMenu>ul>li.'+parentClass+'>ul');
            
        }
        
    }

Конечный результат. Всем спасибо!


Часовой пояс GMT +3, время: 04:13.