README
Interact with Synergy modules/BEM DOM elements
Overview
sQuery is used for interacting with DOM elements that follow the Synergy naming convention.
Example
<div class="foo">
<div class="foo_bar"><div>
<div class="foo_bar-alpha"><div>
</div>
<div class="foo-fizz">
<div class="foo_bar"><div>
<div class="foo_bar-beta"><div>
</div>
sQuery('foo').getComponents('bar').addModifier('buzz');
Result
<div class="foo">
<div class="foo_bar-buzz"><div>
<div class="foo_bar-alpha-buzz"><div>
</div>
<div class="foo-fizz">
<div class="foo_bar-buzz"><div>
<div class="foo_bar-beta-buzz"><div>
</div>
Why?
In a world where DOM elements are becoming more structured and modular, querying DOM elements via classes quickly makes your code become WET, affecting things like readability, scalability and maintainability. The Synergy naming convention (as used above) keeps the DOM as clean and DRY as possible by only requiring one class per element, even if that element has modifiers (learn more).
Consider attempting something like the above using vanilla JS:
// get all `foo` modules
const foos = document.querySelectorAll('.foo, [class*="foo-"]');
foos.forEach(foo => {
// get all `bar` components
const bars = foo.querySelectorAll('.foo_bar, [class*="foo_bar-"]');
bars.forEach(bar => {
// replace old class with new class
bar.classList.forEach(className => {
if (className.indexOf('foo_bar') === 0) {
bar.classList.replace(className, `${className}-buzz`);
}
});
}
});
Some issues here include:
- Repeating the module name
foo
- Repeating the component name
bar
- Awkward
querySelectorAll
query (required to allow the 'one class per element' paradigm) - Hard coded component/modifier glue (typically a non-issue, but still...)
- Order of magnitude more code required than initial 1 line example
Something like this would be a common occurance in projects that use the Synergy naming convention (and indeed any convention that requires you to query DOM elements and manipulate their classList
property, such as BEM), so by identifying and abstracting these commonly-occurring behaviours into their own API, sQuery allows you to interact with structured DOM elements effortlessly by targeting modules and components and adding/removing modifiers to them, allowing you to achieve the above with that one liner from earlier:
sQuery('foo').getComponents('bar').addModifier('buzz');
Checkout these other One-Nexus tools for working with Synergy modules:
- Cell - Style DOM elements that follow the Synergy naming convention (including BEM) using Sass
- Polymorph - Style DOM elements that follow the Synergy naming convention (including BEM) using JavaScript
- Lucid - A set of Higher-Order React Components for rendering UI elements that follow the Synergy naming convention
- Synergy - A front-end framework for creating modular, configurable and scalable UI components (all of the above in one packaged framework)
Installation & Setup
Want to render your DOM elements with React, style them with JavaScript, and interact with them using sQuery? Checkout the Synergy framework instead
npm install --save @onenexus/squery
import 'sQuery' from '@onenexus/squery';
sQuery.init();
See the
sQuery.init()
method for advanced setup
Using BEM? Checkout the Working With BEM page
API
- .add()
- .addModifier()
- .component()
- .components()
- .find()
- .getComponent()
- .getComponents()
- .getModifiers()
- .getModules()
- .getSubComponent()
- .getSubComponents()
- .has()
- .hasModifier()
- .is()
- .isComponent()
- .isModule()
- .modifier()
- .module()
- .modules()
- .parent()
- .parentModule()
- .remove()
- .removeModifier()
- .setComponent()
- .subComponent()
- .subComponents()
- .toggleModifier()
- .unsetComponent()
Usage
The above APIs can be used in the following ways:
sQuery()
function (Recommended)
Return value of - Element(s) retreived via a Synergy query
- Config automatically deteced from global
Synergy
object
See the
sQuery()
page for more information
sQuery(query)[method](...args);
Example
sQuery('.accordion').getComponents('panel');
Property of sQuery
- Element(s) must be explicitly passed as the first argument
- Config must be explicitly passed via the
config
argument
sQuery[method](node, ...args, config);
Example
sQuery.getComponents(document.querySelectorAll('.accordion'), 'panel', {
componentGlue: '_',
modifierGlue: '-'
});
Via Element/NodeList Prototype
- Requires setting up via the
sQuery.init()
method - Automatically passes modifier/component glue
This may be useful and convenient, but use with caution as it is recommended to avoid modifying JavaScript prototypes
Element[method](...args);
NodeList[method](...args);
Example
document.querySelectorAll('.accordion').getComponents('panel');