FarAwayForests

JAB Guide: The Javascript Appendant Builder


Section Quick Links:

What is JAB?

A String-Based JavaScript DOM Manipulator!

JAB stands for the JavaScript Appendant Builder. JAB is a simple, flexible, extremely lightweight element creation and manipulation framework that operates as a single function. The idea behind jab is to let you do more with less, where common actions can be simplified into basic command strings, thus limit the amount of times a programmer has to write "document" or it's common associates. By using JAB for setting up web applications, it allows the amount of data being transferred to be generally smaller and more more compact, allowing JAB to do powerfully build your page using string commands.

Key Points:

The JAB Selector

Selecting Elements

The JAB selector is inspired by the design of the popular jQuery $() selector; however, it allows you to do much more than just select elements through the use of JAB shorthand. This function takes up to two arguments, depending on how you want it to function. The first argument must be a string, object, null, or nothing. Typically JAB will be used with a CSS-style selector string. When the argument passed to the JAB selector is null or nothing, JAB will automatically select the document body. For flexibility, JAB can also take existing element nodes as input, so for example you could select the document body through either of the following ways:

When using string input, JAB identifies based on the string if it can use one of the more efficient selection functions, such as document.getElementsByTagName(), document.getElementsByClassName(), or document.getElementByID(). If it cannot, it then defaults to document.querySelectorAll() for element selection. Because of this, and input like ".container" will end up being a more efficient selection than say "section p:last-of-type"; however, both inputs will work.

Here are examples of JAB Selection using Strings

Simplified DOMContentLoaded Handling:

The second argument must be a boolean. This argument can be omitted to default to true. The second argument controls when JAB will execute:

Examples of DOMContentLoaded handling:

Selection Limiter

JAB offers the ability to limit selections made. This is accomplished by adding the shorthand identifier _[] at the end of the selection string, including a number or a range inside of the brackets. JAB follows the array numbering convention of Javascript, meaning Arrays start at 0.See the examples below for more:

JAB Batches

JAB allows you to combine different selects of elements for batch processing and manipulation. This is accomplished by separating your selection queries using two semi-colons (";;"). All subsequent actions that are taken by JAB will be applied to ALL selected elements in the batch. See the following for examples:

JAB Attributor (Shorthand)

The JAB Attributor is probably the most useful thing about JAB, as it allows so many common page manipulation actions to be accomplished using compact, clean, single lined strings. The JAB attributor has its own callable subsequent function for batching, more on that in the attr() function section further down this page.

The Attributor is called when using the shorthand "&&" after a selector, and followed with the html attributes that you want applied to it. These are space-separated, and starts with either a "+", "=", "-", or "!" depending on what is being applied.

Attributor shorthand ONLY applies to the elements targeted by it's preceding selector query; however, this means that multiple attribute manipulation patterns can be applied in the selection process of multiple elements, and still allow for batch processing, for example:

_("#logo && +.center +{FarAwayForests} +[onclick=someFunction();] ;; .maintext && +.center")

Data Returns

JAB has two data returns:

.node

_(`#something`).node

The node data value is the most simple and straightforward return of JAB. It simply returns the first node of the first target set selected by the JAB selector. For example: If you are looking for the first h1 on the page, or, potentially the only one on the page, instead of using document.querySelector('h1') or document.getElementsByTagName('h1')[0] JAB allows you to select h1, apply attributor shorthand to it if wanted, and then return the selected HTML node all in a more compact statement. _("h1").node

.nodes

Similar to the above 'node' data member, nodes returns ALL elements selected by the JAB selector. If using the ";;" separator for batch selection, nodes will return an array of arrays, organizing the selected items by selector statement. If not using the batch selection separator, nodes will return a single array of all selected elements. Note: This will be an array of HTML nodes, not an HTMLCollection or a NodeList. This is done internally to ensure that forEach statements always work consistently.This means that if you wanted to, you could run your own forEach off of the output of nodes, such as in the example _("p").nodes.forEach(something);

Functions

It is important to note that all of these functions will be applied to all selections in a batch, not just the first selection.

.attr()

This is the stand alone attributor function. It requires a string input using the exact same formatting as covered in the attributor shorthand section above. The primary use-case for this is when you want to create a batch selection to which you want apply attribution changes. consider the following code using the shorthand from the aforementioned section:

_("h2 && +.headingstyle ;; h3 && +.headingstyle ;; h4 && +.headingstyle")

This code selects all h2 elements, and adds the "headingstyles" class to them. Then it selects all h3 elements, and does the same. Then it selects all h4 elements and does the same. The attr() function allows this to be applied to all selects more efficiently, by using

_("h2 ;; h3 ;; h4").attr("+.headingstyle");

Another practically use of this, may be if you have similar styling colors or fonts for all of your headings, and then individual sizing information for each one, note how all of this can easily and quickly be applied in a short JAB string command:

_("h2 && +.h2sizing ;; h3 && +.h3sizing ;; h4 && +.h4sizing").attr("+.generalHeading");

.fill()

The .fill() function takes a single string input, inserting it into the innerHTML data member of all selected elements. WARNING: be careful with this, currently, if you pass a null value into JAB, it will default to the body. Using .fill(''); on a null input will result in the destruction of all inner HTML of the body. If you are going to use the jab selector on elements that are programmatically generated, it may be best to check that the items work before.

.append()

This function takes a single object input, and appends it as a child of every single selected element. Note that this uses node cloning.

.clear()

The .clear() function has no input. It is used to clear the innerHTML data member of all selected elements. The same functionality can be accomplished using .fill("") if so desired.

.remove()

This function has no input. It deletes all selected elements from the DOM.

.create()

The create command is another one of the most powerful functions provided by JAB. Continuing on with the style of string-based DOM manipulation, create() takes a single string argument that follows the CSS-style selector and JAB shorthand notation to create a new element within the the elements of the element(s) defined by the selector. Consider the following:

_(`article`).create(`header.section.text{Continued Reading}`);

This selects all articles on a page, then, creates new "header" elements within each one, adds the classes "section" and "text" to each of these created elements, and sets their inner value to "Continued Reading." The create function is excellent for automating the creation of consistent element patterns. Consider if your website had a series of articles on the page, with the data stored from these articles in a json format. Creating a loop that executes a jab create function can streamline the process of creating these element patterns:

for (const article of arrayOfArticles) {
    _(`main`).create(`article#${article.id}.maincontent`);
    const art = _(`#${article.id}`);
    art.create(`h2{${article.title}}`);
    art.create(`div.socials{socialMediaToolbarHTMLString}`);
    for (const paragraph of article.paragraphs) {
        art.create(`p.content{${paragraph}}`);
    }
}

.build()

Build takes a JAB Object HTML Notation, or, JOHN object input which follows the style of:

{ 
    "tag":"article",
    "id":"someId",
    "classes":["text", "title"],
    content:"Hi there.", 
    "attr":[ {"attr":"value"} ],
    "children":[] 
}

and creates an element following this style. The "children" data field of a JOHN object is an array of other JOHN Objects. The build() function is recursive, and can create create an endless string of elements inside of other elements.

This allows for the easier transfer of build information between servers and JAB. Soon, the build function will also support a "shorthand" field that will work in the same style as the create() function in JAB, further shortening transfer data.

.forEach()

The forEach() function is very simple and straightforward, it takes a single function as an argument, and iterates through every single selected element that has been found by the JAB selector string. It then executes the function for each element. The function passed to it can take each element, or if desired, JAB also can provide the iteration variables. Here is an example showing the use of this function:

_("li ;; dd").forEach((element, setIndex, elementIndex)=>{
    if (elementIndex % 2) element.style.background = 'lightgrey';
});

In this example, the element is the actual element itself, with access to any function that extends a node. The second argument is the set index. The set index will always be 0 unless running a batch process, such as in the case above: the set of elements selected by "li" will be at position 0, and the set selected by "dd" will be at position 1. The element index is the number of the element within the set.

.forEachAt()

Very similar to the previous function, .forEach() takes two arguments, the first an integer, and the second a function. This executes the function through an iteration, but instead of going through an all sets in a batch process, it only goes through a single selection set, located by the integer in the first argument. This gives a developer the flexibility to do something like the following:

_(`li +.aclass ;; dd .another`).forEachAt(1, (element, elementIndex)=>{
    if (elementIndex % 2) element.style.background = 'lightgrey';
});

This allows you to add the 'aclass' to the li tags in your DOM, while in the same line being able to add the 'another' to the dd tags in your DOM, then, run a function that creates a zebra pattern among your dd elements.