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

发布于 2024-11-17 11:13:53 字数 2256 浏览 2 评论 0原文

我们正在使用一个框架,该框架创建由属性 data-type=[some data type] 标识的任意嵌套的 HTML 数据元素。其中每个都可以包含直接输入字段以及其他数据类型,作为单例或数组。嵌套结构唯一的优点是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 查找选择器来获取数据类型< /code> 元素位于给定对象之下的一个 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<3SO。

We're using a framework which creates arbitrarily nested HTML data elements identified by the attribute data-type=[some data type]. Each of these can contain direct input fields as well as other data-type, either as singletons or arrays. The only saving grace of the nesting structure is a data-type will never contain data-types of the same type at any depth.

The HTML I have to work with

<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>

The Selector Problem

I need a JQuery find selector which gets me the set of data-type elements one data-type level beneath the given object:

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

Such that:

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

respectively yields jquery results:

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

JQuery wizards, please help me. You're the only the ones that can.

Answered

This isn't possible with JQuery selectors. I wrapped Patrick's very elegant solution below into a generalized JQuery function-

(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 );

So that:

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

Works as described above. I <3 SO.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅语花开 2024-11-24 11:13:53

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

这个递归深度,但是当找到带有的元素时,任何子分支上的递归都会停止>数据类型,因此只有当有一个子级具有数据类型时,它才会继续。

如果我使用 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 的元素可能具有以下子元素:还有数据类型。如果是这种情况,请将选择器更改为:

var ex = $('#example1');

var res = ex.find('> [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]'

...它将首先获取不具有数据类型的子级,但在这些选择器中,它将获取具有数据类型的子级< /em> 有数据类型

这看起来像你想要的吗?

EDIT 2: I think this is what you're looking for:

var el = $('#example1');

var res = el.children('[data-type]');

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

This one goes recursively deep, but the recursion on any child branch stops when an element is found with data-type, so it only continues as long as there's a child that does not have data-type.

It may be easier to follow if I use a do-while loop, and unwind some of the code:

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

.

.

EDIT: I may have misunderstood one part.

It looks like an element with data-type may have children that also have data-type. If that's the case, change the selector to this:

var ex = $('#example1');

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

So to sum this one up, it says get all children and grandchildren that have a data-type attribute.


Original answer:

If I understand you want children with data-type, and of the children that are not data-type, you need too add their children that are data-type.

var ex = $('#example1');

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

This uses the multiple-selector[docs].

The first selector is:

'> [data-type]'

...which will get children that have a data-type attribute.

The second selector is:

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

...which will first get children that do not have data-type, but of those, it will get their children that do have data-type.

Does that look like what you want?

妖妓 2024-11-24 11:13:53

一个 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;
}

但是,我不确定您是否希望它像这个一样深入。可以将其修改为仅进入特定深度(例如一个或两个级别)。

A POJS function that does what you want and returns an array of the matched element is:

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;
}

However, I'm not sure you want it to go as deep as this one might. It can be modified to only go to a certain depth (say one or two levels).

街道布景 2024-11-24 11:13:53

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

如果我解决了你的问题,

应该可行。选择器 '> [data-type]' 的意思是“给我定义了‘data-type’并且是容器的直接子元素的所有元素。

This

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

should work if I get your problem right.

Selector '> [data-type]' means "give me all elements having 'data-type' defined and that are immediate children of the container.

最笨的告白 2024-11-24 11:13:53
$obj.children().map(function () {return this.name;})

也许?

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

perhaps?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文