Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   find включая self со сложным селектором (https://javascript.ru/forum/jquery/70096-find-vklyuchaya-self-so-slozhnym-selektorom.html)

kazanova84 09.08.2017 17:46

find включая self со сложным селектором
 
Всем доброго времени суток!

Воткнулся в тупик, не могу решить, как лучше сделать. Есть произвольный jquery-селектор, хранящийся в переменной. В документ добавляется некий объект. В этом объекте (контексте) надо найти все элементы, удовлетворяющие селектору, включая сам объект. Иными словами, нужен метод, такой же как find, только включающий в зону поиска исходный объект (контекст), а не только его дочерние элементы.

Поиск по интернету дал такое решение:
var target = $(context).find(selector).addBack(selector);

Но оно не работает для сложных селекторов. Например, если
selector = "#container a";
а context вот такой:
<div id="container"><a href="">link</a></div>

то решение не сработает, на выходе будет пусто. Почему - понять не сложно. find ищет только среди дочерних к context элементов, а addBack берет исходный элемент (context) и фильтрует по селектору, не залезая вглубь дерева. Как элегантно решить - не могу сообразить :-? Структуру документа менять нельзя (т.е. обернуть context в дополнительный div не катит). Взять родительский элемент - тоже, т.к. а) его может не быть, если context = document; б) можно найти лишнее, не относящееся к context. Помогите, плз. Вроде простая задача, а простого решения не вижу

рони 09.08.2017 18:09

Цитата:

Сообщение от kazanova84
а context вот такой:

странный контекст, либо селектор не правильный

рони 09.08.2017 18:17

kazanova84,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

  <script>
$(function() {
var context = "#container", selector = "a";
var target = $(selector,context).addBack();
alert($.map(target,function(el) {
return el.tagName
}));
});
  </script>
</head>

<body>
<div id="container"><a href="">link</a></div>
</body>
</html>

kazanova84 09.08.2017 18:26

Цитата:

Сообщение от рони (Сообщение 461136)
странный контекст, либо селектор не правильный

Это просто пример. Контекст и селектор могут быть условно произвольными. Вот другой пример: https://jsfiddle.net/7mp46of0/6/

kazanova84 09.08.2017 18:28

рони,
Селектор хранится в переменной, и что он из себя представляет - нам не известно. Обработать мы его можем, но вот так легко "располовинить" - нет.

рони 09.08.2017 18:30

Цитата:

Сообщение от kazanova84
Вот другой пример:

нет таблицы в таблице,

нет id в id в первом сообщении.

Цитата:

Сообщение от рони
странный контекст, либо селектор не правильный


рони 09.08.2017 18:33

:write: ... но выход найдётся

рони 09.08.2017 19:00

kazanova84,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

  <script>
$(function() {
var context = "#context", selector = "table a";
var target = $(selector).filter(function(i,el) {
return $(context).find(el).length
}).add(context);

alert($.map(target,function(el) {
return el.tagName
}));
});
  </script>
</head>

<body>
<div id="body">
  <table id="context">
    <tr>
      <td><a>target</a></td>
    </tr>
  </table>
</div>

<div id="body">
  <table id="test">
    <tr>
      <td><a>target</a></td>
    </tr>
  </table>
</div>
</body>
</html>

рони 09.08.2017 19:01

kazanova84,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

  <script>
$(function() {
var context = "#container", selector = "#container a";
var target = $(selector).filter(function(i,el) {
return $(context).has(el).length
}).add(context);

alert($.map(target,function(el) {
return el.tagName
}));
});
  </script>
</head>

<body>
<div id="container"><a href="">link</a></div>
<div id="test"><a href="">link</a></div>
</body>
</html>

Белый шум 10.08.2017 01:17

var s = $(selector);
var res = $(context).find(s).addBack();

https://jsfiddle.net/0jbq9pbe/

рони 10.08.2017 02:03

Белый шум,
твой вариант короче :)

kazanova84 10.08.2017 09:34

Цитата:

Сообщение от Белый шум (Сообщение 461165)
var s = $(selector);
var res = $(context).find(s).addBack();

https://jsfiddle.net/0jbq9pbe/

Вы просто добавляете в результаты поиска исходный контекст, а это неверно. Повторюсь, нужно искать по произвольному селектору, от context включительно и глубже

рони 10.08.2017 10:12

Цитата:

Сообщение от kazanova84
а это неверно

вы проверяли результат? это единственное решение для вашего случая, у Белый шум, короче код, у меня длиннее но алгоритм, один и тотже, найти все элементы по селелектору и отфильтровать(оставить) только те у кого предок context, затем к оставшимся элементам добавлется сам контекст.

kazanova84 10.08.2017 10:29

Цитата:

Сообщение от рони
вы проверяли результат?

Да, в примере выше результат содержит элемент <table> и два элемента <a>, а по селектору должен содержать только <a>.
Цитата:

Сообщение от рони
затем к оставшимся элементам добавлется сам контекст

Контекст может удовлетворять селектору (попадает в результат), а может и не удовлетворять - соответственно не попадает в результат. В данном коде он попадает в результат всегда принудительно

рони 10.08.2017 10:50

kazanova84,
более пас, вашу логику не осилил, всё что мог выше.

Белый шум 10.08.2017 10:55

kazanova84,
ну так уберите .addBack() в конце... Не?

kazanova84 10.08.2017 12:40

Цитата:

Сообщение от Белый шум (Сообщение 461201)
ну так уберите .addBack() в конце... Не?

Не...
Немного переформулировал задачу и решил сам :) Другими словами, постановка звучит так: найти по селектору элементы документа, которые являются самим контекстом или его дочерними элементами. Решил так
var $context = $('#context');
var selector = 'table a';

var res = $(selector).filter(function() {
	return $context.is(this) || ($context.has(this).length > 0);
});


Единственный минус - то, что поиск идет вначале по всему документу, а потом применяется фильтр по контексту. Хорошо бы начинать поиск с контекста. Но тут нюанс: селектор описывает элемент в иерархии документа, а не контекста.

Всем спасибо за участие! :thanks:

Белый шум 10.08.2017 14:34

Цитата:

Сообщение от kazanova84
в примере выше результат содержит элемент <table> и два элемента <a>, а по селектору должен содержать только <a>.

Цитата:

Сообщение от kazanova84
Другими словами, постановка звучит так: найти по селектору элементы документа, которые являются самим контекстом или его дочерними элементами.

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

ADD: чтобы не искать по всему документу, можно так:
$context.parent().find(selector).filter(function() {
    return $context.is(this) || ($context.has(this).length > 0);
});

ADD2: а, у вас же и документ может быть контекстом. Забыл.

Nexus 10.08.2017 15:08

А не скажите, в какой ситуации это может понадобиться?

kazanova84 10.08.2017 18:02

Nexus,
Селекторы ссылаются на элементы, которые нужно неким образом обработать. Когда на страницу вставляется новый контент (ajax) надо этот контент обработать селекторами. Можно, конечно, и классы к обработанным цеплять, но это не очень удобно в контексте кода

Nexus 10.08.2017 19:00

kazanova84, я в данный момент болею, температура, все дела... может быть в этом причина...
Ничего не понял.
Что значит "селекторы ссылаются на элементы"?
Что значит "обработать контент селекторами"?
Что значит "не очень удобно в контексте кода"?


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