q

q is the second of my tiny npm modules, even smaller than the last. It’s to be used with browserify and gives arrays rather than NodeLists from DOM queries.

q wraps querySelector and querySelectorAll in one function, it returns arrays except when there is a single element in which case it returns the element itself:

var q = require('@artcommacode/q')

q('ul li')
// => [ <li>...</li>, <li>...</li>, <li>...</li> ]
q('ul li')[0].textContent
// => $1
q('ul li')[0] === q('ul li:first-of-type')
// => true

Pass an element in as the second argument to run a query on it:

var ul = q('ul')
q('li', ul)
// => [ <li>...</li>, <li>...</li>, <li>...</li> ]

q will return an empty array if no elements are found:

q('ul div')
// => []

The meat of q is only 10 lines:

function toArray(nodeList) {
  return [].slice.call(nodeList)
}

module.exports = function q(query, element) {
  var root = element && document.body.contains(element) ? element : document
  var elements = toArray((root).querySelectorAll(query))
  return elements.length === 1 ? elements[0] : elements
}

And finally, for testing I used substack’s tape and testling. Testling will open a tab in your browser and run tests against an HTML file to display the results in your terminal. It’s a very neat process but the module is now unfortunately unmaintained.

var test = require('tape')
var q = require('../')

test('test q', function (t) {
   var ul = q('ul')
   var li
   t.equal(q('ul li').length, 3)
   t.equal(q('ul li')[0].textContent, '$1')
   t.deepEqual(q('ul li:first-of-type'), q('ul li')[0])
   t.deepEqual(q('ul li'), q('li', ul))
   t.deepEqual(q('ul div'), [])
   t.deepEqual(q('div', li), [])
   t.end()
})

I released this module because I found myself writing something very similiar each time I had to interact with the DOM, wanting to use Array methods such as forEach, filter and reduce on returned elements. It also helps that q() is much shorter than typing document.querySelectorAll()!