复杂的JQuery选择器-如何选择一个任意'代'

Complex JQuery selector - how to select one arbitrary 'generation'?

本文关键字:一个 任意 选择 选择器 JQuery 何选择 复杂      更新时间:2023-09-26

我们使用的框架可以创建由属性data-type=[some data type]标识的任意嵌套的HTML数据元素。其中的每一个都可以包含直接输入字段以及其他data-type,可以是单重态或数组。嵌套结构的唯一优点是data-type在任何深度都不会包含相同类型的data-types

HTML I必须使用

<div data-type='project' id='example1'>
  <input name='start-date'/>
  <div data-type='project-lead' id='example2'>
    <input name='department'/>
    <input name='email'/>
    <div data-type='analyst'>      
      <input name='department'/>
      <input name='email'/>
    </div>
    <div data-type='analyst'>      
      <input name='department'/>
      <input name='email'/>
    </div>
    <div data-type='analyst'>      
      <input name='department'/>
      <input name='email'/>
    </div>
  </div>
  <div class="JustToMakeMyLifeMoreDifficult">
    <div data-type='sponsor'>      
      <input name='department'/>
      <input name='email'/>
    </div>
    <div data-type='sponsor'>      
      <input name='department'/>
      <input name='email'/>
    </div>
  </div>
</div>

选择器问题

我需要一个JQuery查找选择器,它可以在给定对象下一个data-type级别获得一组data-type元素

myData($obj){
  return $obj.find('[data-type]').not([data-type elements further down]);
}

这样:

myData($('#example1'))
myData($('#example2'))

分别产生jquery结果:

[project-lead,sponsor,sponsor]
[analyst, analyst, analyst]

JQuery向导,请帮帮我。你是唯一能做到的人。

已回答

这在JQuery选择器中是不可能的。我将下面Patrick非常优雅的解决方案封装成一个通用的JQuery函数-

(function( $ ){
  $.fn.dataChildren = function(_selector) {
        var iter = this;
        var res = this.children(_selector);
        while ( ( iter = iter.children(':not(' + _selector +')') ).length ) {
                res = res.add(iter.children(_selector));
        }
        return res;
  };
})( jQuery );

因此:

$('#example1').dataChildren('[data-type]')

工程如上所述。I<3 SO

编辑2:我想这就是您想要的:

var el = $('#example1');
var res = el.children('[data-type]');
while ( ( el = el.children(':not([data-type])') ).length ) {
    res = res.add(el.children('[data-type]'));
}

这个递归深入,但当发现具有data-type的元素时,任何子分支上的递归都会停止,所以它只在不具有data-type的子分支存在时才继续。

如果我使用do-while循环,并展开一些代码,可能会更容易理解:

var el = $('#example1');  // el is the current level
var res = $();            // res holds the result
var data_types;           // holds the children with data-type for the current level
do {
      // from current level, get children with data-type
    data_types = el.children('[data-type]'); 
      // add those to the result set
    res = res.add( data_types );
      // make the current level be the children of the current level that
      //      do NOT have data-type
    el = el.children().not( data_types );
} while( el.length ); // continue as long as the new current level
                      //     has at least one element

编辑:我可能误解了其中一部分

看起来具有data-type的元素可能具有也具有data-type的子元素。如果是这种情况,请将选择器更改为:

var ex = $('#example1');
var res = ex.find('> [data-type], > * > [data-type]');

综上所述,它说获取所有具有data-type属性的


原始答案:

如果我知道你想要data-type的孩子,而不是data-type的孩子,你也需要添加他们的data-type的孩子。

var ex = $('#example1');
var res = ex.find('> [data-type], > :not([data-type]) > [data-type]');

这使用multiple-selector[docs]

第一个选择器是:

'> [data-type]'

这将得到具有CCD_ 17属性的子代。

第二个选择器是:

'> :not([data-type]) > [data-type]'

它将首先让的孩子拥有data-type,但在这些孩子中,它将让拥有data-type

这看起来像你想要的吗?

一个POJS函数可以执行您想要的操作并返回匹配元素的数组,它是:

function getNodes(id) {
  var el = (typeof id == 'string')? document.getElementById(id) : id;
  var result = [];
  var node, nodes = el.childNodes;
  var prop = 'data-type';
  var tag = 'div';
  for (var i=0, iLen=nodes.length; i<iLen; i++) {
    node = nodes[i];
    if (node.tagName && node.tagName.toLowerCase() == tag) {
      if (node.getAttribute(prop)) {
        result.push(node);
      } else {
        result = result.concat(getNodes(node));
      }
    }
  }
  return result;
}

然而,我不确定你是否希望它像这次那样深入。它可以被修改为只到达一定的深度(比如一两个级别)。

$obj.find('> [data-type]');

如果我把你的问题解决对了,应该行得通。

选择器'> [data-type]'的意思是"给我所有定义了‘数据类型’并且是容器的直接子级的元素。

$obj.children().map(function () {return this.name;})

也许吧?

相关文章: