,
, , etc.)
rgParents = [];
// collects all nodes of the DOM
while (oWalker.nextNode())
rgParents.push(oWalker.currentNode);
// merges adjacent text nodes to restore the original continuous text after previous operations created multiple separate text nodes
rgParents.forEach(function(oParent)
{
for (var oChild = oParent.firstChild, oNext; oChild; )
if ((oNext = oChild.nextSibling) && oChild.nodeType == 3 && oNext.nodeType == 3) /*Node.TEXT_NODE(3), a text node containing plain text*/
{
oChild.nodeValue += oNext.nodeValue;
oParent.removeChild(oNext);
}
else
oChild = oNext;
});
}
/**
* @description The setExcludeRows() method iterates over the InfoTable rows and assigns the FilterMatchExclude class to rows that do not match the filter
*/
function setExcludeRows()
{
feU(oBody.querySelectorAll("." + INFOTABLE), function(oTable)
{
// checks if the table lists the literals, as a table of Name, Value and Description type
if ( oTable.rows.length > 1 )
if ( NAMEVALUEDESC == oTable.rows[0].innerText.trim() )
for ( var i = 1, l = oTable.rows.length, oRow; (i < l) && (oRow = oTable.rows[i]); i++ )
if ( !oFilter.match(oRow.innerText) )
oRow.classList.add(FILTERMATCHEXCLUDE);
})
}
/**
* @description The resetHighlight() method removes all highlight and inclusion/exclusion effects by restoring original text and clearing applied classes
* @param {callback} [onfinish] Specifies the callback to invoke once the animation ends
*/
function resetHighlight(onfinish)
{
// smoothly includes the rows that match the filter
animateExcludeRows(true /*visible*/, onfinish);
// removes the FilterMatchExclude class, making all rows visible
feU(oBody.querySelectorAll("." + FILTERMATCHEXCLUDE), function(oRow)
{
oRow.classList.remove(FILTERMATCHEXCLUDE);
});
// removes all highlighted words by replacing FilterMatch elements with their original text
unHighlightFilterOccurrences();
}
/**
* @description The findVisibleOf() method finds the first element of the specified class that is fully visible in the viewport
* @param {string} className Specifies the class name to search for
* @returns {Element|null} Returns the first fully visible element, or null if none is visible
*/
function findVisibleOf(className)
{
return feU(document.querySelectorAll('.' + className), function(oElement)
{
var rtElement = oElement.getBoundingClientRect();
return rtElement.top >= 0 && rtElement.bottom <= window.innerHeight && oElement;
}) || null;
}
/**
* @description The animateExcludeRows() method smoothly includes or excludes rows containing the filtered symbols.
* @param {boolean} visible Indicates whether the method should show or hide the rows
* @param {callback} [onfinish] Specifies the callback to invoke once the animation ends
*/
function animateExcludeRows(visible, onfinish)
{
var lonfinish; // {number} represents the setTimeout handle used to trigger the onfinish callback
feU(oBody.querySelectorAll("." + FILTERMATCHEXCLUDE), function(oRow)
{
// makes the row visible to measure heights
if ( visible )
oRow.style.display = "table-row";
// wraps the cell's content in a single custom 'wrap' element, enabling its height to be smoothly animated from 0 to the measured value and back
feU(oRow.children, function(td)
{
// ensures that the 'td' element includes a single 'wrap' custom-element
var oWrap = td.firstElementChild;
if (!oWrap || oWrap.tagName != WRAP)
{
oWrap = document.createElement(WRAP);
while (td.firstChild)
oWrap.appendChild(td.firstChild);
td.appendChild(oWrap);
}
// animates height from 0 -> measured height if visible or reversed if hidden
oWrap.animate(
[
{ height: (visible ? 0 : oWrap.offsetHeight) + PX}, // from
{ height: (visible ? oWrap.offsetHeight : 0) + PX } // to
],
{
duration,
easing
}
).onfinish = function()
{
if ( !visible )
oRow.style.display = "none";
oWrap.style.height = '';
// invokes the callback only after the animation for all rows has finished
if ( onfinish )
{
clearTimeout(lonfinish)
lonfinish = setTimeout(function()
{
onfinish();
})
}
};
})
});
}
nCntCounter++;
try
{
var oBody = document.body, // {HTMLBodyElement} specifies the document's body (CNT's body)
oFilter = getFilter(filter), // {object} indicates the filter object, with values to filter for, that includes the match(value) {boolean} method to verify whether an item matches the filter
o1stHighlight2Fit; // {HTMLElement} specifies the HTML element to be refitted into view when the user clears the filter
// stores the first FILTERMATCH element currently in view so it can be brought back into view when the document is restored
if ( !filter )
if ( o1stHighlight2Fit = findVisibleOf(FILTERMATCH) )
o1stHighlight2Fit = o1stHighlight2Fit.parentElement;
// clears all previously applied highlights and, after the animation completes, ensures the parent of the first visible highlighted match fits into the viewport when the filter is cleared
resetHighlight( !noScrollIntoView && !filter && ensureVisible(o1stHighlight2Fit) ); // ensures the parent of the first highlighted match is visible when the filter is cleared
// applies highlighting to the new matches
if ( filter )
{
// iterates over the InfoTable rows and assigns the FilterMatchExclude class to rows that do not match the filter
setExcludeRows();
// highlights the occurences of the filter
oFilter.terms.forEach(function(oTerm, index)
{
highlightFilterOccurrences(oTerm, index);
})
// ensures the first highlighted match is visible in the viewport
!noScrollIntoView && ensureVisible(document.querySelector('.' + FILTERMATCH));
// smoothly excludes the rows that match the filter
animateExcludeRows(false /*visible*/);
}
}
catch(e)
{
//Uncaught TypeError: Cannot read properties of null (reading 'body')
}
}
/**
* @description The load event is fired when the whole page has loaded, including all dependent resources such as stylesheets and images.
*/
window.addEventListener("load", function(/*event*/)
{
/**
* @description The initTOC() method initializes the `TOC` element (handles the click event of each element to redirect the content to `CNT` element)
*/
function initTOC()
{
/**
* @description The onClickAnhor() method opens the anchor's reference into the `CNT` element
* @param {object} event Indicates the event that generates the click event
*/
function onClickAnhor(event)
{
// prevents any default action
preventDefault(event);
// changes the `CNT`'s source and updates the browser's URL
setSource(this.getAttribute("href"))
}
// replaces the A's click handler for all A-elements of the `TOC` element
feU(toc.getElementsByTagName(A), function(oAnchor)
{
oAnchor.onclick = onClickAnhor;
});
}
/**
* @description The initFilter() method initializes the `Filter` element, so it filters for LI elements of the `TOC`
*/
function initFilter()
{
/**
* @description The onFilter() method is called once the filter is changed to show/hide the LI elements of the `TOC` element
* @param {string} value Specifies the filter (if null/undefined/empty the filter is removed)
* @param {object} event Indicates the event that invoked the onFilter method (called during filter.oninput method)
*/
function onFilter(value, event)
{
/**
* @description The match() method checks whether the item matches the value (filter)
* @param {object} oLI Indicates an "LI" element to verify it it matches the value (filter)
* @returns {boolean} Returns true if the item matches the value (filter)
*/
function match(oLI)
{
/**
* @description The textContent() method gets the content of the node and its descendants, to match the filter
* @param {object} oElement Indicates the element to gets its text
* @returns {string} Returns the the content of the node and its descendants, to match the filter
*/
function textContent(oElement, bFirstLineOnly)
{
var result = oElement.className, // {string} specifies "object", "event", "constant", ...
oAnchorLI; // {object} indicates the inside of LI element
// includes the "property", "method" and "readonly" for "object" LI elements
if ( oElement.classList.contains(OBJECT) )
result = OBJECT + EOL + PROPERTY + EOL + METHOD;
// *Added: Include the "title" (description) and "data-values" (values of an enumeration type) attributes of the inside of LI element, while filtering. Currently, the filter includes the property, method, event or type's name, description and values (for enumeration types) (enum type includes each defined constants such as CheckStateEnum)
if ( oAnchorLI = oElement.firstChild )
{
if ( oAnchorLI.title )
result += EOL + oAnchorLI.title; // includes the "title" attribute
if ( oAnchorLI.dataset && oAnchorLI.dataset.values )
result += EOL + oAnchorLI.dataset.values; // includes "data-values" attribute
}
// includes the text content of the node and its descendants.
return result + EOL + (bFirstLineOnly ? oElement.textContent.trim().split(EOL)[0] || "" : oElement.textContent.trim());
}
/**
* @description The itemContent() method represents the text content of the node and its descendants, to match the filter
* @param {object} oLI Indicates an "LI" element to get its text to filter for
* @returns {string} Returns the text content of the node and its descendants
*/
function itemContent(oLI)
{
var result = textContent(oLI), // {string} indicates the item's text to match
oParentLI; // {string} indicates the item's text to match
if ( oLI.parentElement && (oParentLI = oLI.parentElement.parentElement) && (oParentLI.tagName == "LI") )
result += EOL + textContent(oParentLI, true /*bFirstLineOnly*/);
return result;
}
return oFilter.match(itemContent(oLI));
}
var bExpandAll = !value, // {boolean} specifies whether all "LI" objects should be expanded
oFilter = getFilter(value), // {object} indicates the filter object, with values to filter for, that includes the match(value) {boolean} method to verify whether an item matches the filter
nTopics = 0, // {number} specifies the number of "topic" elements
nHiddenTopics = 0, // {number} specifies the number of "topic" elements being hidden
oActiveLI, // {object} indicates the active "LI" element
bHidden, // {boolean} indicates whether the object is hidden
oCL; // {object} indicates an object of DOMTokenList type that holds classes of the element
// adds or removes the `hidden` class to LI elements of `TOC` that does not match filter
feU(toc.getElementsByTagName("LI"), function(oLI)
{
(oCL = oLI.classList)[updateclassList(match(oLI))].call(oCL, HIDDEN);
});
// adds or removes the `hidden` class to "object"/LI elements of `TOC` that dislays no properties/methods
feU(toc.getElementsByClassName(OBJECT), function(oObjectLI)
{
oCL = oObjectLI.classList;
bHidden = oObjectLI.getElementsByClassName(HIDDEN).length == oObjectLI.getElementsByTagName("LI").length;
oCL[updateclassList(!bHidden)].call(oCL, HIDDEN);
!bHidden && oCL[updateclassList(bExpandAll)].call(oCL, EXPANDED);
})
// adds or removes the `hidden` class to "topic"/DIV elements of `TOC` that does not match filter
feU(toc.getElementsByClassName(TOPIC), function(oTopicDiv)
{
nTopics++;
bHidden = oTopicDiv.getElementsByTagName("LI").length == oTopicDiv.getElementsByClassName(HIDDEN).length;
(oCL = oTopicDiv.classList)[updateclassList(!bHidden)].call(oCL, HIDDEN);
bHidden && nHiddenTopics++;
});
// adds or removes the `hidden` class to `TOC` itself, when no match
nTopics && (oCL = toc.classList)[updateclassList(nTopics != nHiddenTopics)].call(oCL, HIDDEN);
// expands or collapses the "LI" elements
feU(toc.getElementsByClassName(OBJECT), function(oLI)
{
(oCL = oLI.classList)[updateclassList(bExpandAll)].call(oCL, EXPANDED);
})
// updates the "filter" value
!event && (filter.value = value);
// adds or removes the `close` class to parent element of "filter" element
(oCL = filter.parentElement.classList)[updateclassList(!filter.value)].call(oCL, CLOSE);
// updates the browser's `F` param
setP(PARAM.F, value || null /*removes if empty string*/);
// ensures that the active "LI" element fits the scroll view
(oActiveLI = toc.getElementsByClassName("active").item(0)) && setTimeout(function()
{
expEnsureVisible(oActiveLI);
})
// delays updating the filter highlights in the content document while the user is typing
clearTimeout(lCntFilter);
lCntFilter = setTimeout(function()
{
cntHighlightFilter(cnt.contentDocument, filter.value);
}, duration)
}
// adds the input `Filter` and span close elements to display the `Filter` field
var divF = document.getElementById(F), // {object} indicates the DIV element that displays the `Filter`
span; // {object} specifies the SPAN to display `✖` character
if ( divF )
{
// creates and adds the input `Filter` field
filter = document.createElement("INPUT");
filter.setAttribute("type", "text");
filter.setAttribute("id", "Filter");
filter.setAttribute("placeHolder", "Filter for...");
filter.oninput = function(event) // The oninput attribute fires when the value of an or