-
16 Dec 2011 4:32 PM #1
Unanswered: DomQuery equivalent to Ext.Element.up?
Unanswered: DomQuery equivalent to Ext.Element.up?
I need to find a parent node based on a complex selector, such as that supported by DomQuery. However, it's only obvious to me how to find a child element using DomQuery.
Is there any way to use DomQuery to find parent nodes? Or, is it possible to use advanced selectors using Ext.Element.up?
Specifically, I'm trying to find parent nodes based on the value of an attribute that happens to contain brackets.
For example:
I need a way to isolate the children of the second container <div>. The way I'd like to be able to do it:HTML Code:<div class="widget" foo="bar[]"> <div class="widget" id="foo1"></div> <div class="widget" id="foo2"></div> <div class="widget" id="foo3"></div> <div class="widget" id="foo4"></div> </div> <div class="widget" foo="baz"> <div class="widget" id="foo5"></div> <div class="widget" id="foo6"></div> <div class="widget" id="foo7"></div> <div class="widget" id="foo8"></div> </div>
If I do this, then the browser freezes, consuming 100% CPU of the core on which the browser is running.Code:Ext.each(Ext.query('.widget'), function() { var el = Ext.get(this); if (!!el.up('.widget') && !el.up('.widget[foo$="[]"]')) { // should only see foo5, foo6, foo7, foo8 here } });
-
16 Dec 2011 5:07 PM #2
The selectors available when using the element methods child, down, parent, up, select, query, is, first, last, next and prev are all pretty much the same. They all use DomQuery behind the scenes.
I don't know of an escaping mechanism that would allow you to do what you want in a selector but it should be pretty easy to achieve by other means.
This would work:
or maybe this:Code:Ext.each(Ext.query('.widget[foo=baz] .widget'), function(dom) { ... });
Code:Ext.each(Ext.query('.widget .widget'), function(dom) { var el = Ext.get(dom); if (el.up('.widget').getAttribute('foo').indexOf('[]') === -1) { ... } });
-
17 Dec 2011 6:28 AM #3
Thanks for your reply, skirtle. I perhaps should have mentioned that this works without a problem:
It's only when I use this same selector in an Ext.Element method (such as up) that the browser freezes. Continuing from the last example:Code:var widgets = Ext.query('.widget[foo$="[]"]'); // in this specific example, returns a single-element array with the first parent <div> // as a bare HTMLElement.
Since the API documentation does specify "simple selector" for the Ext.Element methods' selector argument, combined with this problem I'm having, I figured that DomQuery was not used for Ext.Element.Code:Ext.each(widgets, function() { var el = Ext.get(this); var parent = el.up('.widget[foo$="[]"]'); if (!!parent) console.log("nested bracket widget found!"); });
Your alternative approaches would work with my simple example, but they would not work in practice. The markup could look like the example I gave, or it could arbitrarily look like this:
Unfortunately, Ext.Element.up only goes as far as the first match and then stops. Without resorting to writing a recursive function or something just for this one specific case, then in order to either target or completely avoid that top element, I need to be able to specify the complete set of criteria in the selector.HTML Code:<div class="widget" foo="bar[]"> <div class="widget" id="fooA"> <div class="widget id="fooB"> <div class="widget" id="foo1"></div> <div class="widget" id="foo2"></div> <div class="widget" id="foo3"></div> <div class="widget" id="foo4"></div> </div> </div> </div> <div class="widget" foo="baz"> <div class="widget" id="foo5"></div> <div class="widget" id="foo6"></div> <div class="widget" id="foo7"></div> <div class="widget" id="foo8"></div> </div>
Since what I want to do works using Ext.query, if Ext.Element's methods truly do use DomQuery behind the scenes, then perhaps this should be filed as a bug...?
-
17 Dec 2011 9:00 AM #4
Ah. Seems my original answer was somewhere between unclear, untrue and unhelpful. Let's see if I can do better this time...
DomQuery has 2 modes of operation, select and simple. You can see this here:
http://docs.sencha.com/ext-js/4-0/#!...method-compile
Various things only support simple selectors, including the DomQuery methods filter and is. Some of the methods I mentioned on Ext.Element use one of these methods on DomQuery, including the ones that deal with ancestors.
Exactly what constitutes a simple selector doesn't appear to be well documented. The CSS 3 spec defines the same term and I think the intention is that that definition applies here. That said, the way I read the spec, the examples given in the ExtJS docs wouldn't count as simple selectors, so I'm left pretty unclear about what that means. From a bit of experimenting it seems to restrict the use of all the bits that would be useful for what you're trying to do.
The net result is that this is the best way I've found so far to find the elements you want:
I fully intend to dig into this further when I get more time because there's definitely something fishy going on with 'simple selectors'.Code:var doms = Ext.Array.filter(Ext.query('.widget .widget'), function(dom) { for (var el = Ext.fly(dom) ; el ; el = el.parent('.widget')) { if ((el.getAttribute('foo') || '').indexOf('[]') !== -1) { return false; } } return true; });






Reply With Quote