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

时间:2011-06-28 01:58:27

标签: javascript jquery selector children

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

HTML 必须使用

<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选择器是不可能的。我将下面帕特里克非常优雅的解决方案包含在一个通用的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]')

如上所述工作。我&lt; 3 SO。

4 个答案:

答案 0 :(得分:2)

编辑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]'

...将获得具有data-type属性的孩子。

第二个选择器是:

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

...首先会让的孩子拥有data-type,但是那些会让他们的孩子拥有{{1} }}

这看起来像你想要的吗?

答案 1 :(得分:1)

执行所需操作并返回匹配元素数组的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;
}

然而,我不确定你是否希望它像这个一样深。它可以修改为仅达到某个深度(比如一个或两个级别)。

答案 2 :(得分:0)

$obj.find('> [data-type]');
如果我的问题得到解决,

应该有效。

选择器'> [data-type]'的意思是“给我所有定义了'数据类型'的元素,这些元素是容器的直接子元素。

答案 3 :(得分:0)

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

也许?