1. #1
    Ext JS Premium Member cparker's Avatar
    Join Date
    Dec 2008
    Location
    Boston, Massachusetts, USA
    Posts
    19
    Vote Rating
    0
    cparker is on a distinguished road

      0  

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

    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>
    I need a way to isolate the children of the second container <div>. The way I'd like to be able to do it:

    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
        }
    });
    If I do this, then the browser freezes, consuming 100% CPU of the core on which the browser is running.

  2. #2
    Sencha Premium Member skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,509
    Answers
    528
    Vote Rating
    288
    skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future

      0  

    Default


    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:

    Code:
    Ext.each(Ext.query('.widget[foo=baz] .widget'), function(dom) {
        ...
    });
    or maybe this:

    Code:
    Ext.each(Ext.query('.widget .widget'), function(dom) {
        var el = Ext.get(dom);
    
        if (el.up('.widget').getAttribute('foo').indexOf('[]') === -1) {
            ...
        }
    });

  3. #3
    Ext JS Premium Member cparker's Avatar
    Join Date
    Dec 2008
    Location
    Boston, Massachusetts, USA
    Posts
    19
    Vote Rating
    0
    cparker is on a distinguished road

      0  

    Default


    Thanks for your reply, skirtle. I perhaps should have mentioned that this works without a problem:

    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.
    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:
    Ext.each(widgets, function() {
        var el = Ext.get(this);
        var parent = el.up('.widget[foo$="[]"]');
        if (!!parent) console.log("nested bracket widget found!");
    });
    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.

    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:

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

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

  4. #4
    Sencha Premium Member skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,509
    Answers
    528
    Vote Rating
    288
    skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future skirtle has a brilliant future

      0  

    Default


    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:

    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;
    });
    I fully intend to dig into this further when I get more time because there's definitely something fishy going on with 'simple selectors'.

Thread Participants: 1

Tags for this Thread