JQuery - найти всех потомков на любом уровне, но не потомков этих потомков - PullRequest
4 голосов
/ 18 октября 2019

ВОПРОС:

Я пытаюсь использовать JQuery .find(), чтобы найти всех потомков в элементе на любом уровне , которые имеют данный атрибут, но непотомки тех потомков с тем же атрибутом.

ПОМОЧЬ ПОНИМАНИЕ:

JQuery

Предполагаемая цельзапрос ниже - найти всех потомков в элементе $("#some_id") (на любом уровне), имеющих атрибут some_attribute, но не потомков тех потомков с таким же атрибутом.

$("#some_id").find("[some_attribute]");

HTML

<span id="some_id" some_attribute>
    <span some_attribute> <!-- SELECT -->
        <span some_attribute> <!-- IGNORE -->
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
        <span>
        </span>
    </span>
    <span>
        <span some_attribute> <!-- SELECT -->
            <span>
                <span some_attribute> <!-- IGNORE -->
                </span>
            </span>
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
    </span>
    <span>
        <span>
            <span>
                <span some_attribute> <!-- SELECT -->
                </span>
            </span>
        </span>
    </span>
</span>

ПРИМЕЧАНИЕ: мне нужен общий подход ... я объясню лучше! Предположим, я не знаю селектор $("#some_id") У меня есть только результат этого запроса. Также учтите, что этот результат может относиться к элементу, который может находиться внутри другого элемента с атрибутом some_attribute.

Ответы [ 2 ]

3 голосов
/ 18 октября 2019

Вы можете использовать :not, чтобы убедиться, что выбранные элементы не соответствуют определенному селектору - здесь, #some_id [some_attribute] [some_attribute] (потому что элементы, которые соответствуют этому селектору, будут some_attribute вложенными в другой some_attribute, который не является#some_id):

const result = $("#some_id")
  .find("[some_attribute]:not(#some_id [some_attribute] [some_attribute])")
  .each(function() {
    console.log(this.innerHTML);
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="some_id" some_attribute>
    <span some_attribute>sel <!-- SELECT -->
        <span some_attribute> <!-- IGNORE -->
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
        <span>
        </span>
    </span>
    <span>
        <span some_attribute>sel <!-- SELECT -->
            <span>
                <span some_attribute> <!-- IGNORE -->
                </span>
            </span>
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
    </span>
    <span>
        <span>
            <span>
                <span some_attribute>sel <!-- SELECT -->
                </span>
            </span>
        </span>
    </span>
</span>

Если вы не можете жестко запрограммировать его, я полагаю, можно было бы установить атрибут так, чтобы вы могли правильно использовать :not:

const elm = $("#some_id");
elm[0].dataset.parent = '';
elm
  .find("[some_attribute]:not([data-parent] [some_attribute] [some_attribute])")
  .each(function() {
    console.log(this.innerHTML);
  });
elm[0].removeAttribute('data-parent');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="some_id" some_attribute>
    <span some_attribute>sel <!-- SELECT -->
        <span some_attribute> <!-- IGNORE -->
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
        <span>
        </span>
    </span>
    <span>
        <span some_attribute>sel <!-- SELECT -->
            <span>
                <span some_attribute> <!-- IGNORE -->
                </span>
            </span>
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
    </span>
    <span>
        <span>
            <span>
                <span some_attribute>sel <!-- SELECT -->
                </span>
            </span>
        </span>
    </span>
</span>

Если вы также не хотите менять DOM, .filter и убедитесь, что элемент .closest с [some_attribute] является родительским:

const elm = $("#some_id");
elm
  .find("[some_attribute]")
  .filter(function() {
    return $(this).parent().closest('[some_attribute]')[0] === elm[0];
  })
  .each(function() {
    console.log(this.innerHTML);
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="some_id" some_attribute>
    <span some_attribute>sel <!-- SELECT -->
        <span some_attribute> <!-- IGNORE -->
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
        <span>
        </span>
    </span>
    <span>
        <span some_attribute>sel <!-- SELECT -->
            <span>
                <span some_attribute> <!-- IGNORE -->
                </span>
            </span>
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
    </span>
    <span>
        <span>
            <span>
                <span some_attribute>sel <!-- SELECT -->
                </span>
            </span>
        </span>
    </span>
</span>

Используя старые версии jQuery, вы можете использовать .selector:

const elm = $("#some_id");
const sel = elm.selector;
elm
  .find(`[some_attribute]:not(${sel} [some_attribute] [some_attribute])`)
  .each(function() {
    console.log(this.innerHTML);
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<span id="some_id" some_attribute>
    <span some_attribute>sel <!-- SELECT -->
        <span some_attribute> <!-- IGNORE -->
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
        <span>
        </span>
    </span>
    <span>
        <span some_attribute>sel <!-- SELECT -->
            <span>
                <span some_attribute> <!-- IGNORE -->
                </span>
            </span>
            <span some_attribute> <!-- IGNORE -->
            </span>
        </span>
    </span>
    <span>
        <span>
            <span>
                <span some_attribute>sel <!-- SELECT -->
                </span>
            </span>
        </span>
    </span>
</span>
0 голосов
/ 21 октября 2019

Вот мое решение. Для получения дополнительной информации см. Примечания к коду ниже ...

// NOTE: Find all descendants at any level, but not the descendants of those descendants.
// By Questor
function findDescsNotDescsOfThose(jqPntElOrPntQry, jqFind){
    var jqElInst;
    if (typeof jqPntElOrPntQry === "string" || 
            jqPntElOrPntQry instanceof String) {
    // [Ref.: https://stackoverflow.com/a/9436948/3223785 ]

        jqElInst = $(jqPntElOrPntQry);
    } else {
        jqElInst = jqPntElOrPntQry;
    }
    return jqElInst.find(jqFind)
        .filter(function(){

            // NOTE: We need use ".parent ()" and then ".closest ()", otherwise ".closest ()"
            // will find the element itself if it fits "jqFind". By Questor
            descOfjqFind = $(this).parent().closest(jqFind);

            // NOTE: Checks if it is not descended from any element that also fits
            // in "jqFind". Being descended from an element that also fits "jqFind"
            // checks to see if this element is descended from "jqElInst". By Questor
            if (descOfjqFind.length > 0 && $(descOfjqFind).
                    parent().closest(jqElInst).length === 1) {
                return false
            }

            return true;
    });
}

Спасибо! = D

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