/************************************ REVISION LOG ENTRY Revision By: Mihai Filimon ( mfl@exontrol.com ) Created on 11/23/2020 10:00:00 AM Modified on 02/25/2022 11:00:00 AM (*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)) Modified on 09/19/2022 10:50:00 AM (includes support for @media only screen and (max-width: 580px)) Modified on 06/18/2024 09:30:00 AM (*Fixed: The resizing of the navbar section of the frame pauses when the cursor hovers over the content area (right panel)) Modified on 11/07/2025 09:30:00 AM (*NEW: Highlights matches and filters the document while typing) Comments: help.js, help.css This code may be used in compiled form in any way you desire. This file may not be redistributed modified or unmodified without the authors written consent. ************************************/ /////////////////////////////////////////////////////////// (QP) (QueryParam) // // The QP namespace provides functions to update or query the URL parameters. // // The QP namespace includes definitions for the following methods: // // Split(url) {object}, splits the URL into location, params and hash parts, as an object of {a(ll),u(rl),h(ash),l(ocation),p(arams)} type // Add(url, param, value) {string}, adds(replaces) the parameter of the specified url and returns the new url(adds/replaces "param=value" or "param") // Del(url, param) {string}, removes the parameter of the specified url and returns the new url // Has(url, param) {string}, gets the value of the specified parameter within the giving url (returns null if no parameter is found) // /////////////////////////////////////////////////////////// /** * @description Creates the QP namespace */ QP = function() { /** * @description The split() method splits the URL into location, params and hash parts, as an object of {a(ll),u(rl),h(ash),l(ocation),p(arams)} type * @param {string} url A string expression that defines the URL to split * @returns {object} Returns an object of {a(ll),u(rl),h(ash),l(ocation),p(arams)} type as explained: * * a(ll) {string}, indicates the unsplited URL (as it was provided) * u(rl) {string}, specifies the URL without the # hash section (location + params) * h(ash) {string}, indicates empty string or the # hash section (includes the '#' character) * l(ocation) {string}, specifies the location of the URL (the string precceding the ? character, includes protocol, domain and path) * p(arams) {string}, specifies the query-parameters of the URL (the string after the ? character, includes '?' character) * */ function split(url) { var iHash = String(url || "").indexOf('#'), // {number} indicates the position of '#' character within the url (-1 if not found) u = ~iHash ? url.substr(0, iHash).trim() : url, // {string} specifies the URL without the # hash section (location + params) iParam = u.indexOf('?'); // {number} indicates the position of '?' character within the url (-1 if not found) return { a: url, // a(ll) {string}, indicates the unsplited URL (as it was provided) u: u, // u(rl) {string}, specifies the URL without the # hash section (location + params) h: ~iHash ? url.substr(iHash).trim() : "", // h(ash) {string}, indicates empty string or the # hash section (includes the '#' character) l: ~iParam ? u.substr(0, iParam).trim() : u, // l(ocation) {string}, specifies the location of the URL (the string precceding the ? character, includes protocol, domain and path) p: ~iParam ? u.substr(iParam).trim() : "", // p(arams) {string}, specifies the query-parameters of the URL (the string after the ? character, includes '?' character) } } /** * @description The getParamEx() method gets the regular-expression to search for the parameter * @param {string} param Specifies the name of the parameter to look for * @returns {object} Returns an object of RegExp type */ function getParamEx(param) { return new RegExp("[?&]" + param + "($|[&]|=[^&]*)", "i"); } /** * @description The add() method adds(replaces) the parameter of the specified url (adds/replaces "param=value" or "param") * @param {string} url Specifies an URL to change * @param {string} param Indicates the name of the parameter to add * @param {string} value Specifies the value of the parameter to add * @returns {string} Returns the new URL (includes the added parameter) */ function add(url, param, value) { var oURL = split(url), oParamEx = getParamEx(param = String(param || "").trim()), separator = oURL.u.indexOf('?') != -1 ? "&" : "?", oMatch = oURL.u.match(oParamEx); // builds the value as "param=value" or "param" if ( value = String(value || "").trim() ) value = "=" + value; value = param + value; // adds or replaces the parameter return (oMatch ? oURL.u.substr(0,oMatch.index + 1) + value + oURL.u.substr(oMatch.index + oMatch[0].length) : oURL.u + separator + value) + oURL.h } /** * @description The del() method removes the parameter of the specified url * @param {string} url Specifies an URL to change * @param {string} param Indicates the name of the parameter to delete * @returns {string} Returns the new URL (excludes the parameter) */ function del(url, param) { var oURL = split(url); url = oURL.u.replace(getParamEx(String(param || "").trim()), ''); if (url.slice(-1) == '?') url = url.slice(0, -1); // removes the last ? character if any if (url.indexOf('?') < 0) url = url.replace(/&/, '?'); // replace the first occurrence of & by ? if no ? is present return url + oURL.h; } /** * @description The has() method gets the value of the specified parameter within the giving url (returns undefined if no parameter is found) * @param {string} url Specifies an URL to query * @param {string} param Indicates the name of the parameter to request * @returns {string} Returns null (no parameter found), or a string expression that defines the value of the giving parameter (could be empty string) */ function has(url, param) { var oParam = split(url).u.match(getParamEx(param = String(param || "").trim())), // {array} returns the matches, as an Array object nEqual; // {number} specifies the position of the "=" character inside the match if ( oParam ) { oParam = oParam[0]; nEqual = oParam.indexOf("="); oParam = ~nEqual ? oParam.substr(nEqual + 1) : ""; } return oParam; } return { /** * @description The Split(url) method splits the URL into location, params and hash parts, as an object of {a(ll),u(rl),h(ash),l(ocation),p(arams)} type * @param {string} url A string expression that defines the URL to split * @returns {object} Returns an object of {a(ll),u(rl),h(ash),l(ocation),p(arams)} type as explained: * * a(ll) {string}, indicates the unsplited URL (as it was provided) * u(rl) {string}, specifies the URL without the # hash section (location + params) * h(ash) {string}, indicates empty string or the # hash section (includes the '#' character) * l(ocation) {string}, specifies the location of the URL (the string precceding the ? character, includes protocol, domain and path) * p(arams) {string}, specifies the query-parameters of the URL (the string after the ? character, includes '?' character) * * @example * * QP.Split("http://exontrol.com/rhelp.jsp?product=exgrid#bookmark") * * returns: * * { * a:'http://exontrol.com/rhelp.jsp?product=exgrid#bookmark' * h:'#bookmark' * l:'http://exontrol.com/rhelp.jsp' * p:'?product=exgrid' * u:'http://exontrol.com/rhelp.jsp?product=exgrid' * } */ Split: split, /** * @description The Add(url, param, value) method adds(replaces) the parameter of the specified url and returns the new url (adds/replaces "param=value" or "param") * @param {string} url Specifies an URL to change * @param {string} param Indicates the name of the parameter to add * @param {string} value Specifies the value of the parameter to add * @returns {string} Returns the new URL (includes the added parameter) * @example * * QP.Add("http://exontrol.com/rhelp.jsp?product=exgrid#bookmark","src","InsideZooms_default") * * returns: * * "http://exontrol.com/rhelp.jsp?product=exgrid&src=InsideZooms_default#bookmark" */ Add: add, /** * @description The Del(url, param) method removes the parameter of the specified url and returns the new url * @param {string} url Specifies an URL to change * @param {string} param Indicates the name of the parameter to add * @returns {string} Returns the new URL (excludes the parameter) * @example * * QP.Del("http://exontrol.com/rhelp.jsp?product=exgrid#bookmark","product") * * returns: * * "http://exontrol.com/rhelp.jsp#bookmark" */ Del: del, /** * @description The Has(url, param) method gets the value of the specified parameter within the giving url (returns null if no parameter is found) * @param {string} url Specifies an URL to query * @param {string} param Indicates the name of the parameter to request * @returns {string} Returns null (no parameter found), or a string expression that defines the value of the giving parameter (could be empty string) * @example * * QP.Has("http://exontrol.com/rhelp.jsp?product=exgrid#bookmark","product") * * returns: * * "exgrid" */ Has: has }; }(); /** * @description The oDEF variable holds definition for several options */ var VERSION = "25.11", // {string} specifies the version of the help system, as "year.month" EXPANDED = "expanded", // {string} specifies the class name to expand the object OBJECT = "object", // {string} specifies the class name that defines an object PROPERTY = "property", // {string} specifies the class name that defines a property METHOD = "method", // {string} specifies the class name that defines a method READONLY = "readonly", // {string} specifies the class name that defines a method TOPIC = "topic", // {string} specifies the class name that defines a topic HIDDEN = "hidden", // {string} specifies the name of the class for non-visible elements ACTIVE = "active", // {string} specifies the name of the class to activate a "LI" element GLYPH = "glyph", // {string} specifies the name of the class that displays the expand/collapse glyphs CLOSE = "close", // {string} specifies the name of the class/identifier that displays the filter's close button PX = "px", // {string} indicates the px-units TOC = "TOC", // {string} indicates the identifier of the document's `TOC` element (Table of Contents) CNT = "CNT", // {string} indicates the identifier of the document's `CNT` element (Content) F = "F", // {string} specifies the identifier of the DIV that hosts the `Filter` element (Parent-Filter) FILTER = "Filter", // {string} indicates the identifier of the document's `Filter` element (Filter) L = "L", // {string} indicates the identifier of the document's `L` element (Left side) R = "R", // {string} indicates the identifier of the document's `R` element (Right side) PARAM = // {object} defines the parameters of the current document { S: "S", // {string} specifies the source to display (indicates the URL to set for `CNT` element) F: "F" // {string} specifies the current filter }, EOL = "\n", // {string} defines the EOL character INFOTABLE = "InfoTable", FILTERMATCH = "FilterMatch", FILTERMATCHEXCLUDE = "FilterMatchExclude", WRAP = "WRAP", NAMEVALUEDESC = "Name\tValue\tDescription", nCntCounter = 0, // {number} indicates the number of times the cntHighlightFilter method has been invoked duration = 250, // {number} specifies the speed in ms of the animation for including or excluding literals in the InfoTable easing = 'ease', // {string} controls how the animation progresses over time, such as linear, accelerating, or decelerating. lCntFilter; // {number} stores the current handle of the timer that initiates the cntHighlightFilter /** * @description The feU/forEachUntil() method invokes the callback for each element of the HTMLCollection object until it returns a truly value (handy function to enumerate the elements of HTMLCollection) * @param {callback} callback Specifies the function of callback(oElement) {boolean} type that's invoked for each element * @returns {any} Returns undefined or the result of the last callback */ function feU(collection, callback) { var oResult; for ( var oItem of collection ) if ( oResult = callback(oItem) ) return oResult; } /* function feU(collection, callback) { var oResult; for ( var i = 0, l = collection.length; !oResult && i < l; i++ ) oResult = callback(collection.item(i)); return oResult; } */ /** * @description The getFilter() method builds the filter object used to match values against multiple terms * @param {string} filter Specifies the filter string that could include multiple terms separated by space * @returns {object} Returns an object of {terms, match()} type as explained: * * terms {array}, holds the regular expressions for each filter term * match(value) {boolean}, method that determines whether the value matches all filter terms * * @example * * if ( getFilter("term1 term2").match("This is term1 and term2") ) * console.log("The value matches all filter terms"); * */ function getFilter(filter) { var rgTerms = []; // {array} holds the terms by lenght (longest first) to avoid matching smaller terms that are part of larger terms // splits the filter value to extract terms combined with AND for searching or filtering filter != null && (filter = String(filter).trim()).split(" ").forEach(function(value) { (value = value.trim()) && rgTerms.push(value); }); // sorts the terms by lenght (longest first) rgTerms.sort(function(a, b) { return b.length - a.length; }); // removes duplicate terms or terms that are part of other terms rgTerms = rgTerms.filter(function(term, index) { term = term.toLocaleLowerCase(); for ( var i = 0; i < index; i++ ) if ( ~rgTerms[i].toLocaleLowerCase().indexOf(term) ) return false; // removes the term if it's part of another term return true; }); // builds the rgResult result return { /** * @description The terms field holds the regular expressions for each filter term, as an array of [RegExp] type * @type {array} */ terms: rgTerms.map(function(term) { return new RegExp(term, "gi") // {RegExp} m(atch) specifies the regular expression used for searching as g(lobal) and i(gnorecase) }), /** * @description The match() method determines whether the value matches all filter terms * @param {string} value Specifies the value to match against all filter terms * @returns {boolean} Returns true if the value matches all filter terms, else false */ match: function(value) { return !feU(this.terms, function(oTerm) { return !value.match(oTerm); }) } } } /** * @description The expEnsureVisible() method expands any collapsed parent elements and scrolls the specified element into view if necessary * @param {object} oElement Specifies the element to fit the view's client area (scroll into the view) */ function expEnsureVisible(oElement) { /** * @description The scrollIntoL() method scrolls the element to fit its parent ("L" part) client area * @param {object} oElement Specifies the element to fit the view's client area (scroll into the view) */ function scrollIntoL(oElement) { /** * @description The getScrollParent() method determines the parent-element responsible to scroll the element * @param {object} oElement Specifies the element to fit the view's client area (scroll into the view) * @returns {object} Returns the parent-element responsible to scroll the element */ function getScrollParent(oElement) { while (oElement && !/(auto|scroll)/.test(getComputedStyle(oElement).overflow) ) oElement = oElement.parentElement; return oElement; } var rtElement = oElement.getBoundingClientRect(), oScrollParent = getScrollParent(oElement), rtContainer = oScrollParent.getBoundingClientRect(), topFixedHeight = 56, bottomFixedHeight = 4 + (oScrollParent.offsetHeight - oScrollParent.clientHeight), // height of the scroll bar scrollBy = 0, dy = 0; if ( (dy = rtElement.top - topFixedHeight) < 0 ) scrollBy = dy; else if ( (dy = (rtElement.bottom - (rtContainer.bottom - bottomFixedHeight))) > 0 ) scrollBy = dy; scrollBy && oScrollParent.scrollBy( { behavior: "smooth", top: scrollBy }) } if ( oElement ) { var oCL, // {object} indicates an object of DOMTokenList type that holds classes of the element o; // {object} holds a reference to an HTML element // adds `expanded` class to "LI" of `object` class (expand the object that contains the property) ((oElement.classList.contains(OBJECT) && (oCL = oElement.classList)) || ((o = oElement.parentElement) /*