Dojo in XPages – 7: Selecting DOM Elements with dojo.query

In the last post, I showed how to easily select an individual element on the page by its ID with dojo. In this post, we’ll look at dojo.query(), a far more powerful feature that lets you select and manipulate multiple elements on the page.

Dojo in XPages Series

Dojo in XPages — All Blog Posts

dojo.query()

dojo.query() is automatically available in XPages — it does not require loading an additional module.

It selects any number of elements on the page that match the CSS selector that you provide. You can choose elements based on the tag, class, id, attributes, or any combination thereof.

It can be used to access multiple elements and manipulate them simultaneously. When you run a query, it returns a NodeList.

What is a NodeList?

A NodeList which is an array of elements with additional functions available to make it more convenient to process (more on those in the next post). Even if the query only returns one element, an array is returned.

Selecting Elements

The same CSS selectors you use to target elements with stylesheet properties are used for selecting elements with dojo.query. You can select elements by tag name, class name, ID, use pseudoselectors, or combine them as needed for more specific targeting.

The selector is a string, so it can either be hard-coded or it can be replaced with a variable.

Standard Examples

Here are some of examples of how to use dojo.query to select elements:

Description Example
To select elements by tag name, specify the tag name dojo.query('li');
To select an element by ID, specify a pound sign (#) then the ID dojo.query('#myID');
To select elements by class name – specify a dot (.), then the class name dojo.query('.myClass');
To select elements of a specific tag with a specific class, specify the element name, a dot (.), then the class name dojo.query('li.myClass');
Select all img tags within any div that has the myDiv class dojo.query('div.myDiv img');
Select all elements that have a specific attribute dojo.query('[size]');
Select all elements with an attribute that has a specific value dojo.query('[size=5]');
Select odd or even elements with a pseudo class dojo.query('li:nth-child(odd)');

dojo.query('li:nth-child(even)');

Check out this W3Schools page for more information on CSS selectors. The better you understand them, the more efficiently you can target the elements you want to select on your page.

Test with Browser Tools!

As I mentioned in the last post, it can dramatically streamline your development when you work on code snippets directly in the browser console, rather than changing event code in XPages, saving, building, and refreshing the page.

This is especially true with working out query selectors. When you test a dojo query in the console, you’ll see an array of elements returned.

Dojo 7 - BrowserTools

To get a quick count of the number of elements a query will return, you can add .length to the end of the statement to get the array length.

Selecting XPages Components – A Caveat

The query selector cannot handle the colons that are part of every XPages component ID, so if you want to use dojo.query() to select a component by its ID, you’ll need to use the string replace() method in JavaScript to escape the colons so the query can be executed properly.

Does not work:
dojo.query('#view:_id1:inputText1');

dojo.query('##{id:inputText1}');

Works:
dojo.query('#view\\:_id1\\:inputText1');

dojo.query('##{id:inputText1}'.replace(/:/g, '\\:'));

The last example looks a little strange because of the double pound sign (#); the first pound sign specifies that you’re selecting an ID, then #{id:inputText1} is the EL syntax that gets replaced with the XPages component’s client-side JavaScriptID. The replace code uses a regular expression to replace all colons in the ID with \\:

There are two backslashes because the backslash is an escape character; the first backslash escapes the second one, so the resulting string has one backslash.

With all of that being said, the code is kind of confusing. It is often simpler to add an attribute or class name to XPages elements, so the dojo query can be easier to understand and maintain.

Up Next

dojo.query() is the starting point for a lot of dojo functionality. Now that we can select elements on the page, we’ll start looking at how to manipulate them in future posts.

Advertisements

14 responses to “Dojo in XPages – 7: Selecting DOM Elements with dojo.query”

  1. troyreimer says :

    To select an XPages element I often use a selector like this –> dojo.query(“[id$=’inputText1′]”). The “$” tells the query to find an id that ends with ‘inputText1’. This won’t work in all cases, for instance if you name your fields “red_inputText1”, “blue_inputText1”, but it can be powerful.

  2. jeremyhodge says :

    I’ve done a lot with this – and i’ll share a caveat – don’t use the full id. For cross browser and backwards compatibility. Some browsers have a limit on how many characters are in the ID before it fails to find them. IE and older versions of firefox in particular. The colons also seem to cause an issue. Typically, I’ll be very careful to name the IDs uniquely and short, and then use the “ends in” query …

    For example, given an xp:div with an id “MyDiv”, I would use the following query to maximize compatibility:

    dojo.query(“[id$=’MyDiv’]”)

  3. Csaba Kiss says :

    Brad, I love your tutorials. No fluff, just pure useful information. I found a grammatical error on this page though. This sentence needs to be corrected:

    “A NodeList which an array of elements with additional functions available to make it more convenient to process (more on those in the next post).”

    I am looking forward to more comprehensive Dojo tutorials, perhaps, dgrid?

  4. Sean Haggerty says :

    dojo.query() fails to find nodes by attribute when the target is a dijit-widget containing attributes
    Q: How do we find a dijit node to add events to, when dojo.query cain’t find’em?

    i.e.
    Normal xp:input: var res = dojo.query(‘[normalAttr]’); // returns results

    Dijit’field xp:input: var pairs = dojo.query(‘[dojoAttr]’); //returns nothing
    var pairs = dojo.query(‘[plainAttr]’); //returns nothing

    • Sean Haggerty says :
       
      
      	
      		
      	
      
      
    • Sean Haggerty says :

      3rd time’s a charm to show an example
      dojo.query() fails to find nodes by attribute when the target is a dijit-widget containing attributes
      Q: How do we find a dijit node to add events to, when dojo.query cain’t find’em?

      i.e.
      Normal xp:input: var res = dojo.query(‘[normalAttr]‘); // returns results
      [xp:inputText id=”inputText1″]
      [xp:this.attrs]
      [xp:attr name=”normalAttr” value=”findable”][/xp:attr]
      [/xp:this.attrs]
      [/xp:inputText]

      Dijit’fied xp:input: var pairs = dojo.query(‘[dojoAttr]‘); //returns nothing
      var pairs = dojo.query(‘[plainAttr]‘); //returns nothing
      [xp:inputText id=”inputText2″ dojoType=”dijit.form.DateTextBox”]
      [xp:this.dojoAttributes]
      [xp:dojoAttribute name=”dojoAttr” value=”true”][/xp:dojoAttribute]
      [xp:dojoAttribute name=”intermediateChates” value=”true”][/xp:dojoAttribute]
      [/xp:this.dojoAttributes]
      [xp:this.attrs]
      [xp:attr name=”plainAttr” value=”true”][/xp:attr]
      [/xp:this.attrs]
      [/xp:inputText]

      • Brad Balassaitis says :

        You’re absolutely right that any dijits will completely change the output of the control, so it’s not as straightforward. A Dojo Date Text Box and a regular Edit Box with the date picker enabled will be modified and output similarly.

        Dojo.query will run on the actual page output, so one option would be to inspect the output and adjust the query accordingly.

        If you want to get a handle to the input that stores the value, you could use this:

        dojo.query(‘div.dijitDateTextBox div.dijitInputContainer input[type=”hidden”]’);

      • Brad Balassaitis says :

        To attach an event, you’ll want to get one of the higher-level div tags above the input that’s storing the value.

      • Brad Balassaitis says :

        Another option that you have is to add a class name to the control via the Style subtab of the Properties view. In both the Edit Box with date picker and the Dojo Date Text Box, the class name will be carried through to the top-level div in the dijit output, so it can be used to select it with a query like this:

        dojo.query(‘.myClassName’);

  5. Csaba Kiss says :

    I am a beginner XPage developer and just began learning about it. I would like to specialize myself in the Dojo part of Xpages. I have a conundrum though. As far as I see, most XPage tutorials on Dojo uses the “older” syntax and version of the framework such as dojo.query, dojo.byId and so on. If I go to the official Dojo website, they strongly discourage the use of this old way and want everybody to use the new way such as:
    require([
    ‘dojo/dom’,
    ‘dojo/dom-construct’
    ], function (dom, domConstruct) { …
    }.
    The newest version of extension library supports Dojo 1.9.2. What’s the general consensus on this? Since I am new to this, I would rather use the new system, if that works with XPages, however, finding tutorials for that is rather hard.
    On another note, has anyone attended the Sitepen workshops? Are they useful for Xpage developers?

  6. seanshaggerty says :

    Where did you put the dojo js , that we see in the image above?
    thx

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: