diff --git a/src/core/js/ext_references.js b/src/core/js/ext_references.js index e25de2107072af4a9227e00c5a4af2bca08d7996..13210b60a63c7f12d3678ba225bb4fa889fcb662 100644 --- a/src/core/js/ext_references.js +++ b/src/core/js/ext_references.js @@ -22,7 +22,6 @@ * ** end header */ - /* * Check if an element is out of the viewport * @@ -33,8 +32,7 @@ * @param {Node} elem - The element to check * @return {Object} A set of booleans for each side of the element. */ -var isOutOfViewport = function (elem) { - +var isOutOfViewport = function(elem) { // Get element's bounding var bounding = elem.getBoundingClientRect(); @@ -42,18 +40,15 @@ var isOutOfViewport = function (elem) { var out = {}; out.top = bounding.top < 0; out.left = bounding.left < 0; - out.bottom = bounding.bottom > (window.innerHeight || - document.documentElement.clientHeight); + out.bottom = bounding.bottom > + (window.innerHeight || document.documentElement.clientHeight); out.right = bounding.right > - (window.innerWidth || document.documentElement.clientWidth); - out.any = - out.top || out.left || out.bottom || out.right; - out.all = out.top && - out.left && out.bottom && out.right; + (window.innerWidth || document.documentElement.clientWidth); + out.any = out.top || out.left || out.bottom || out.right; + out.all = out.top && out.left && out.bottom && out.right; return out; }; - /** * @module reference_list_summary * @version 0.1 @@ -63,117 +58,114 @@ var isOutOfViewport = function (elem) { * * @author Timm Fitschen */ -var reference_list_summary = new function () { - - var logger = log.getLogger("reference_list_summary"); - - /** Return a condensed string representation of an array of integers. - * - * @example simplify_integer_numbers([1,2,3,5,8,9,10]) returns "1-3, 5, - * 8-10" - * - * @example simplify_integer_numbers([]) returns "" - * - * @example simplify_integer_numbers([1]) returns "1" - * - * @example simplify_integer_numbers([1,2]) returns "1, 2" because an array - * with two elements gets a special treatment. - * - * The array may be unsorted. simplify_integer_numbers([1,2,3]) returns - * "1-3" simplify_integer_numbers([2,1,3]) returns "1-3" as well - * - * The array may contain duplicates. simplify_integer_numbers([1,2,2,3]) - * returns "1-3" - * - * @param {numbers} array - unsorted array of integers, possibly with - * duplicates. @return {string} a condensed string representation of the - * array. - */ - this.simplify_integer_numbers = function (array) { - logger.trace("enter simplify_integer_numbers", array); - var set = Array.from(new Set(array)); - - if (set.length === 0) { - return "" - } else if (set.length === 1) { - return `${set[0]}`; - } - - // sort numerically - set.sort((a, b) => a - b); - - if (set.length === 2) { - return `${set[0]}, ${set[1]}`; - } - - - var ret = `${set[0]}`; - var last = undefined; - // set[0]; - - // e.g. [1,2,3,4,5,8,9,10]; - for (const next of set) { - // append '-' to summarize consecutive numbers - if (next - last === 1 && !ret.endsWith("-")) { - ret += "-"; - } - - if (next - last > 1) { - - if (ret.endsWith("-")) { - // close previous interval and start new - ret += `${last}, ${next}`; - } else { - // no previous interval, start interval. - ret += `, ${next}`; - } - } else if (next === set[set.length - 1]) { - // finish interval if next is last item - ret += next; - break; - } - - - last = next; - - } - - // e.g. "1-5, 8-10" - return ret; - } - - /** - * Generate a summary of all reference_infos by calling the callback - * function of the first reference_info in the array. - * - * The summary is appended to the summary_container if available and - * returned (for testing purposes). - * - * Returns undefined, if ref_infos is empty or does not come with a - * callback function. - * - * @param {reference_info[]} ref_infos - array of reference_infos. - * @param {HTMLElement} summary_container - the summary is appended to this - * element. - * @return {HTMLElement|string} generated summary - */ - this.generate = function (ref_infos, summary_container) { - logger.trace("enter generate", ref_infos); - if (ref_infos.length > 0 && - typeof ref_infos[0].callback === "function") { - const summary = - ref_infos[0].callback(ref_infos); - if (summary && summary_container) { - $(summary_container).append(summary); - } - logger.trace("leave generate", summary); - return summary; - } - logger.trace("leave generate, return undefined"); - return undefined; - } -} - +var reference_list_summary = + new function() { + var logger = log.getLogger("reference_list_summary"); + + /** + * Return a condensed string representation of an array of integers. + * + * @example simplify_integer_numbers([1,2,3,5,8,9,10]) returns "1-3, 5, + * 8-10" + * + * @example simplify_integer_numbers([]) returns "" + * + * @example simplify_integer_numbers([1]) returns "1" + * + * @example simplify_integer_numbers([1,2]) returns "1, 2" because an + * array with two elements gets a special treatment. + * + * The array may be unsorted. simplify_integer_numbers([1,2,3]) returns + * "1-3" simplify_integer_numbers([2,1,3]) returns "1-3" as well + * + * The array may contain duplicates. simplify_integer_numbers([1,2,2,3]) + * returns "1-3" + * + * @param {numbers} array - unsorted array of integers, possibly with + * duplicates. @return {string} a condensed string representation of the + * array. + */ + this.simplify_integer_numbers = + function(array) { + logger.trace("enter simplify_integer_numbers", array); + var set = Array.from(new Set(array)); + + if (set.length === 0) { + return ""; + } else if (set.length === 1) { + return `${set[0]}`; + } + + // sort numerically + set.sort((a, b) => a - b); + + if (set.length === 2) { + return `${set[0]}, ${set[1]}`; + } + + var ret = `${set[0]}`; + var last = undefined; + // set[0]; + + // e.g. [1,2,3,4,5,8,9,10]; + for (const next of set) { + // append '-' to summarize consecutive numbers + if (next - last === 1 && !ret.endsWith("-")) { + ret += "-"; + } + + if (next - last > 1) { + + if (ret.endsWith("-")) { + // close previous interval and start new + ret += `${last}, ${next}`; + } else { + // no previous interval, start interval. + ret += `, ${next}`; + } + } else if (next === set[set.length - 1]) { + // finish interval if next is last item + ret += next; + break; + } + + last = next; + } + + // e.g. "1-5, 8-10" + return ret; + }; + + /** + * Generate a summary of all reference_infos by calling the callback + * function of the first reference_info in the array. + * + * The summary is appended to the summary_container if available and + * returned (for testing purposes). + * + * Returns undefined, if ref_infos is empty or does not come with a + * callback function. + * + * @param {reference_info[]} ref_infos - array of reference_infos. + * @param {HTMLElement} summary_container - the summary is appended to + * this element. + * @return {HTMLElement|string} generated summary + */ + this.generate = function(ref_infos, summary_container) { + logger.trace("enter generate", ref_infos); + if (ref_infos.length > 0 && + typeof ref_infos[0].callback === "function") { + const summary = ref_infos[0].callback(ref_infos); + if (summary && summary_container) { + $(summary_container).append(summary); + } + logger.trace("leave generate", summary); + return summary; + } + logger.trace("leave generate, return undefined"); + return undefined; + }; + }; /** * @module resolve_references @@ -184,366 +176,390 @@ var reference_list_summary = new function () { * @author Timm Fitschen * @author Alexander Schlemmer */ -var resolve_references = new function () { - - var logger = log.getLogger("resolve_references"); - - var _scroll_timeout = undefined; - - // bind global function to local context for unit testing - this.retrieve = retrieve; - this.getParents = getParents; - - /** - * This event is dispatched on the summary container after the summary has - * been generated and appended to the container. - */ - this.summary_ready_event = new Event("resolve_references.summary.ready"); - - /** - * Scroll listener calls {@link resolve_references.update_visible_references} 500 milliseconds after the - * last scroll event. - */ - var scroll_listener = () => { - if (_scroll_timeout) { - clearTimeout(_scroll_timeout); - } - _scroll_timeout = setTimeout(function () { - resolve_references.update_visible_references(); - }, 500); +var resolve_references = + new function() { + var logger = log.getLogger("resolve_references"); + + var _scroll_timeout = undefined; + + // bind global function to local context for unit testing + this.retrieve = retrieve; + this.getParents = getParents; + + /** + * This event is dispatched on the summary container after the summary has + * been generated and appended to the container. + */ + this.summary_ready_event = new Event("resolve_references.summary.ready"); + + /** + * Scroll listener calls {@link + * resolve_references.update_visible_references} 500 milliseconds after + * the last scroll event. + */ + var scroll_listener = () => { + if (_scroll_timeout) { + clearTimeout(_scroll_timeout); + } + _scroll_timeout = setTimeout( + function() { + resolve_references.update_visible_references(); + }, + 500); + }; + + /** + * Initilize the scroll listener which triggers the resolution of the + * entity ids and trigger it for the first time in order to resolve all + * visible references. + */ + this.init = + function() { + if ("${BUILD_MODULE_EXT_RESOLVE_REFERENCES}" === "ENABLED") { + scroll_listener(); + + // mainly for vertical scrolling + $(window).scroll(scroll_listener); + + // for horizontal scrolling. + $(".caosdb-value-list").scroll(scroll_listener); + } + }; + + /** + * Check if an element is inside of the viewport on the vertical axis. + * + * Returns true if any of the element's bounding box's top or bottom + * edges are in the viewport. + * + * @param {HTMLElement} elem - the element to check @return {boolean} + * + */ + this.is_in_viewport_vertically = + function(elem) { + var out = isOutOfViewport(elem); + return !(out.top || out.bottom); + }; + + /** + * Check if an element is inside of the viewport on the + * horizontal axis. + * + * This criterion is very much different from the vertical + * correspondent: It looks for the parent which contains the list + * scroll bar for LinkAhead values. Then it is checked whether the + * element's bounding box is visible inside the scroll box. + * + * @param {HTMLElement} elem - the element to + * check @return {boolean} + * + */ + this.is_in_viewport_horizontally = + function(elem) { + var scrollbox = elem.parentElement.parentElement; + // Check this condition only if the grand parent is a list and return + // true otherwise. + if (scrollbox.classList.contains("caosdb-value-list") == true) { + var boundel = elem.getBoundingClientRect(); + var boundscroll = scrollbox.getBoundingClientRect(); + var leftcrit = boundel.right > boundscroll.left; + var rightcrit = boundel.left < boundscroll.right; + return leftcrit && rightcrit; + } else { + return true; + } + }; + + /** + * Return true iff the entity has at least one direct parent + * named `par`. + * + * @param {HTMLElement} entity - entity in HTML + * representation. @param + * {string} par - parent name. @return {boolean} + */ + this.is_child = + function(entity, par) { + var pars = resolve_references.getParents(entity); + for (const thispar of pars) { + if (thispar.name === par) { + return true; + } + } + return false; + }; + + /** + * @typedef {reference_info} + * @property {string} text + * @property {function} callback - a callback function + * with one parameter + * (`data`) which generates a summary from the array + * of data objects which are passed to this function. + * @property {object} data - an object with properties + * which can be understood and used by the `callback` + * function. + */ + + /** + * Return a reference_info for an entity. + * + * You may add your own custom resolver by specifying a JS + * module via the `BUILD_EXT_REFERENCES_CUSTOM_RESOLVER` + * build variable. The custom resolver has to be a JS + * module (typically located at + * linkahead-webui/src/ext/js), the name of which is given + * as the value of `BUILD_EXT_REFERENCES_CUSTOM_RESOLVER`. + * It has to provide a `resolve` function that takes the + * entity id to be resolved as a string and returns a + * `reference_info` object with the resolved custom + * reference as a `text` property. + * + * See + * linkahead-webui/src/core/js/reference_resolver/caosdb_default_person.js + * for an example. + * + * TODO refactor to be configurable. + * @async @param {string} id - the id of the entity which + * is to be resolved. @return {reference_info} + */ + this.resolve_reference = + async function(id) { + const custom_reference_resolver = + window["${BUILD_EXT_REFERENCES_CUSTOM_RESOLVER}"]; + if (custom_reference_resolver && + typeof custom_reference_resolver.resolve === "function") { + // try custom_reference_resolver and fall-back to standard + // implementation + var ret = await custom_reference_resolver.resolve(id); + if (ret) { + return ret; + } + } + + + + const entity = (await resolve_references.retrieve(id))[0]; + + // TODO handle multiple parents + const par = resolve_references.getParents(entity)[0] || {}; + const name = getEntityName(entity); + + var ret = { + "text": id + }; + if (par.name === "TestReferenced" && + typeof resolve_references.test_resolver === "function") { + // this is a test case, initialized by the test suite. + ret = resolve_references.test_resolver(entity); + } else if (typeof name !== "undefined" && name.length > 0) { + ret["text"] = name; + } else if (getEntityHeadingAttribute(entity, "path") !== undefined || + par.name == "Image") { + // show file name + var pths = getEntityHeadingAttribute(entity, "path").split("/"); + ret["text"] = pths[pths.length - 1]; + } + + return ret; + }; + + this._target_class = + "caosdb-resolve-reference-target"; + + /** + * Add a target span where the resolved reference information can be + * shown. + * + * If the element has a target yet, the existing one is returned. + * + * @param {HTMLElement} element - where to append the target. + * @return {HTMLElement} the new/existing target element. + */ + this.add_target = + function(element) { + if (element.getElementsByClassName(this._target_class).length > 0) { + return element.getElementsByClassName(this._target_class); + } else { + return $(`<span class="${this._target_class}"/>`) + .appendTo(element)[0]; + } + }; + + /** + * Retrieve meaningful information for a single + * caosdb-f-reference-value element. + * + * @param {HTMLElement} rs - resolvable reference link + * @return {reference_info} the resolved reference information + */ + this.update_single_resolvable_reference = + async function(rs) { + $(rs).find(".caosdb-id-button").hide(); + const target = resolve_references.add_target(rs); + const id = getEntityID(rs); + target.textContent = id; + const resolved_entity_info = + (await resolve_references.resolve_reference(id)); + target.textContent = resolved_entity_info.text; + return resolved_entity_info; + }; + + /** + * Add a summary field to the the list_values element. + * + * A summary field is a DIV element with class + * `caosdb-resolve-reference-summary`. The summary field is used + * to display a condensed string representation of the referenced + * entities in the list-property. + * + * @param {HTMLElement} list_values - where to add the summary + * field. + * @return {HTMLElement} a summary field. + */ + this.add_summary_field = + function(list_values) { + const summary = + $(`<div class="${resolve_references._summary_class}"/>`); + $(list_values).prepend(summary); + return summary[0]; + }; + + this._summary_class = "caosdb-resolve-reference-summary"; + + /** + * All references which have not yet been resolved are contained in an + * HTML Element with this css class. + */ + this._unresolved_class_name = "caosdb-resolvable-reference"; + + this.get_resolvable_properties = + function(container) { + const _unresolved_class_name = this._unresolved_class_name; + return $(container) + .find(".caosdb-f-property-value") + .has(`.${_unresolved_class_name}`) + .toArray(); + }; + + /** + * This function updates all references in the body which are inside + * of the current viewport. + * + * If the optional container parameter is given, only elements inside + * the container are being processed. + * + * @param {HTMLElement} container + */ + this.update_visible_references = async function(container) { + const property_values = resolve_references.get_resolvable_properties( + container || document.body); + + const _unresolved_class_name = + resolve_references._unresolved_class_name; + + // Loop over all property values in the container element. Note: each + // property_value can be a single reference or a list of references. + for (const property_value of property_values) { + var lists = findElementByConditions( + property_value, x => x.classList.contains("caosdb-value-list"), + x => x.classList.contains("caosdb-preview-container")); + lists = $(lists).has(`.${_unresolved_class_name}`); + + if (lists.length > 0) { + logger.debug("processing list of references", lists); + + for (var i = 0; i < lists.length; i++) { + const list = lists[i]; + if (resolve_references.is_in_viewport_vertically(list)) { + const rs = $(list) + .find(`.${_unresolved_class_name}`) + .toggleClass(_unresolved_class_name, false); + + // First resolve only one reference. If the `ref_info` + // indicates that a summary is to be generated from the + // list of references, retrieve all other other + // references. Otherwise retrieve only those which are + // visible in the viewport horizontally and trigger the + // retrieval of the others when they are scrolled into + // the view port. + const first_ref_info = + await resolve_references.update_single_resolvable_reference( + rs[0]); + + first_ref_info["index"] = 0; + + if (typeof first_ref_info.callback === "function") { + // there is a callback function, hence we need to + // generate a summary. + logger.debug("loading all references for summary", rs); + const summary_field = + resolve_references.add_summary_field(property_value); + + // collect ref infos for the summary + const ref_infos = [first_ref_info]; + for (var j = 1; j < rs.length; j++) { + const ref_info = + resolve_references.update_single_resolvable_reference( + rs[j]); + ref_info["index"] = j; + ref_infos.push(ref_info); + } + + // wait for resolution of references, + // then generate the summary, + // dispatch event when ready. + Promise.all(ref_infos) + .then(_ref_infos => { + reference_list_summary.generate(_ref_infos, + summary_field); + }) + .then(() => { + summary_field.dispatchEvent( + resolve_references.summary_ready_event); + }) + .catch((err) => { + logger.error(err); + }); + + } else { + // no summary to be generated + + logger.debug("lazy loading references", rs); + for (var j = 1; j < rs.length; j++) { + // mark others to be loaded later and only if + // visible + $(rs[j]).toggleClass(_unresolved_class_name, true); + } + } + } + } + } + + // Load all remaining references. These are single reference values + // and those references from lists which are left for lazy loading. + const rs = findElementByConditions( + property_value, + x => x.classList.contains(`${_unresolved_class_name}`), + x => x.classList.contains("caosdb-preview-container")); + for (var i = 0; i < rs.length; i++) { + if (resolve_references.is_in_viewport_vertically(rs[i]) && + resolve_references.is_in_viewport_horizontally(rs[i])) { + logger.debug("processing single references", rs); + $(rs[i]).toggleClass(_unresolved_class_name, false); + + // discard return value as it is not needed for any summary + // generation as above. + resolve_references.update_single_resolvable_reference(rs[i]); + } + } + } + }; }; - - /** - * Initilize the scroll listener which triggers the resolution of the - * entity ids and trigger it for the first time in order to resolve all - * visible references. - */ - this.init = function () { - if ("${BUILD_MODULE_EXT_RESOLVE_REFERENCES}" === "ENABLED") { - scroll_listener(); - - // mainly for vertical scrolling - $(window).scroll(scroll_listener); - - // for horizontal scrolling. - $(".caosdb-value-list").scroll(scroll_listener); - } - } - - /** - * Check if an element is inside of the viewport on the vertical axis. - * - * Returns true if any of the element's bounding box's top or bottom edges are - * in the viewport. - * - * @param {HTMLElement} elem - the element to check @return {boolean} - * - */ - this.is_in_viewport_vertically = function (elem) { - var out = - isOutOfViewport(elem); - return !(out.top || out.bottom); - } - - /** Check if an element is inside of the viewport on the horizontal axis. - * - * This criterion is very much different from the vertical correspondent: It - * looks for the parent which contains the list scroll bar for LinkAhead values. - * Then it is checked whether the element's bounding box is visible inside the - * scroll box. - * - * @param {HTMLElement} elem - the element to check @return {boolean} - * - */ - this.is_in_viewport_horizontally = function (elem) { - var scrollbox = elem.parentElement.parentElement; - // Check this condition only if the grand parent is a list and return true - // otherwise. - if (scrollbox.classList.contains("caosdb-value-list") == - true) { - var boundel = elem.getBoundingClientRect(); - var boundscroll = scrollbox.getBoundingClientRect(); - var leftcrit = boundel.right > boundscroll.left; - var rightcrit = boundel.left < boundscroll.right; - return leftcrit && rightcrit; - } else { - return true; - } - } - - - /** - * Return true iff the entity has at least one direct parent named `par`. - * - * @param {HTMLElement} entity - entity in HTML representation. @param - * {string} par - parent name. @return {boolean} - */ - this.is_child = function (entity, par) { - var pars = resolve_references.getParents(entity); - for (const thispar of pars) { - if (thispar.name === par) { - return true; - } - } - return false; - } - - /** - * @typedef {reference_info} - * @property {string} text - * @property {function} callback - a callback function with one parameter - * (`data`) which generates a summary from the array of data objects - * which are passed to this function. - * @property {object} data - an object with properties which can be - * understood and used by the `callback` function. - */ - - /** - * Return a reference_info for an entity. - * - * You may add your own custom resolver by specifying a JS module - * via the `BUILD_EXT_REFERENCES_CUSTOM_RESOLVER` build - * variable. The custom resolver has to be a JS module (typically - * located at linkahead-webui/src/ext/js), the name of which is given - * as the value of `BUILD_EXT_REFERENCES_CUSTOM_RESOLVER`. It has - * to provide a `resolve` function that takes the entity id to be - * resolved as a string and returns a `reference_info` object with - * the resolved custom reference as a `text` property. - * - * See linkahead-webui/src/core/js/reference_resolver/caosdb_default_person.js - * for an example. - * - * TODO refactor to be configurable. @async @param {string} id - the id of - * the entity which is to be resolved. @return {reference_info} - */ - this.resolve_reference = async function (id) { - const custom_reference_resolver = window["${BUILD_EXT_REFERENCES_CUSTOM_RESOLVER}"]; - if (custom_reference_resolver && typeof custom_reference_resolver.resolve === "function") { - // try custom_reference_resolver and fall-back to standard implementation - var ret = await custom_reference_resolver.resolve(id); - if (ret) { - return ret; - } - } - - const entity = (await resolve_references.retrieve(id))[0]; - - // TODO handle multiple parents - const par = resolve_references.getParents(entity)[0] || {}; - const name = getEntityName(entity); - - var ret = { - "text": id - }; - if (par.name === "TestReferenced" && typeof resolve_references.test_resolver === "function") { - // this is a test case, initialized by the test suite. - ret = resolve_references.test_resolver(entity); - } else if (typeof name !== "undefined" && name.length > 0){ - ret["text"] = name; - } else if (getEntityHeadingAttribute(entity, "path") !== - undefined || par.name == "Image") { - // show file name - var pths = getEntityHeadingAttribute(entity, "path") - .split("/"); - ret["text"] = pths[pths.length - 1]; - } - - - return ret; - } - - - this._target_class = "caosdb-resolve-reference-target"; - - /** - * Add a target span where the resolved reference information can be shown. - * - * If the element has a target yet, the existing one is returned. - * - * @param {HTMLElement} element - where to append the target. - * @return {HTMLElement} the new/existing target element. - */ - this.add_target = function (element) { - if(element.getElementsByClassName(this._target_class).length > 0){ - return element.getElementsByClassName(this._target_class); - } else { - return $(`<span class="${this._target_class}"/>`) - .appendTo(element)[0]; - } - } - - /** - * Retrieve meaningful information for a single caosdb-f-reference-value - * element. - * - * @param {HTMLElement} rs - resolvable reference link - * @return {reference_info} the resolved reference information - */ - this.update_single_resolvable_reference = async function (rs) { - $(rs).find(".caosdb-id-button").hide(); - const target = resolve_references.add_target(rs); - const id = getEntityID(rs); - target.textContent = id; - const resolved_entity_info = ( - await resolve_references.resolve_reference(id)); - target.textContent = resolved_entity_info.text; - return resolved_entity_info; - } - - - /** - * Add a summary field to the the list_values element. - * - * A summary field is a DIV element with class - * `caosdb-resolve-reference-summary`. The summary field is used to display - * a condensed string representation of the referenced entities in the - * list-property. - * - * @param {HTMLElement} list_values - where to add the summary field. - * @return {HTMLElement} a summary field. - */ - this.add_summary_field = function (list_values) { - const summary = $( - `<div class="${resolve_references._summary_class}"/>`); - $(list_values).prepend(summary); - return summary[0]; - } - - this._summary_class = "caosdb-resolve-reference-summary"; - - /** - * All references which have not yet been resolved are contained in an HTML - * Element with this css class. - */ - this._unresolved_class_name = "caosdb-resolvable-reference"; - - this.get_resolvable_properties = function (container) { - const _unresolved_class_name = this._unresolved_class_name; - return $(container).find(".caosdb-f-property-value").has( - `.${_unresolved_class_name}`).toArray(); - } - - - /** - * This function updates all references in the body which are inside of the - * current viewport. - * - * If the optional container parameter is given, only elements inside the - * container are being processed. - * - * @param {HTMLElement} container - */ - this.update_visible_references = async function (container) { - const property_values = resolve_references - .get_resolvable_properties(container || document.body); - - const _unresolved_class_name = resolve_references - ._unresolved_class_name; - - // Loop over all property values in the container element. Note: each property_value can be a single reference or a list of references. - for (const property_value of property_values) { - var lists = findElementByConditions( - property_value, - x => x.classList.contains("caosdb-value-list"), - x => x.classList.contains("caosdb-preview-container")) - lists = $(lists).has(`.${_unresolved_class_name}`); - - if (lists.length > 0) { - logger.debug("processing list of references", lists); - - for (var i = 0; i < lists.length; i++) { - const list = lists[i]; - if (resolve_references - .is_in_viewport_vertically(list)) { - const rs = $(list).find( - `.${_unresolved_class_name}`) - .toggleClass(_unresolved_class_name, false); - - // First resolve only one reference. If the `ref_info` - // indicates that a summary is to be generated from the - // list of references, retrieve all other other - // references. Otherwise retrieve only those which are - // visible in the viewport horizontally and trigger the - // retrieval of the others when they are scrolled into - // the view port. - const first_ref_info = await resolve_references - .update_single_resolvable_reference(rs[0]); - - first_ref_info["index"] = 0; - - if (typeof first_ref_info.callback === "function") { - // there is a callback function, hence we need to - // generate a summary. - logger.debug("loading all references for summary", - rs); - const summary_field = resolve_references - .add_summary_field(property_value); - - // collect ref infos for the summary - const ref_infos = [first_ref_info]; - for (var j = 1; j < rs.length; j++) { - const ref_info = resolve_references - .update_single_resolvable_reference(rs[j]); - ref_info["index"] = j; - ref_infos.push(ref_info); - } - - // wait for resolution of references, - // then generate the summary, - // dispatch event when ready. - Promise.all(ref_infos) - .then(_ref_infos => {reference_list_summary - .generate(_ref_infos, summary_field);}) - .then(() => { - summary_field.dispatchEvent( - resolve_references - .summary_ready_event - );}) - .catch((err) => { - logger.error(err); - }) - - } else { - // no summary to be generated - - logger.debug("lazy loading references", rs); - for (var j = 1; j < rs.length; j++) { - // mark others to be loaded later and only if - // visible - $(rs[j]).toggleClass(_unresolved_class_name, true); - } - } +$(document) + .ready(function() { + if ("${BUILD_MODULE_EXT_RESOLVE_REFERENCES}" === "ENABLED") { + caosdb_modules.register(resolve_references); } - } - } - - // Load all remaining references. These are single reference values - // and those references from lists which are left for lazy loading. - const rs = findElementByConditions( - property_value, - x => x.classList.contains(`${_unresolved_class_name}`), - x => x.classList.contains("caosdb-preview-container")); - for (var i = 0; i < rs.length; i++) { - if (resolve_references.is_in_viewport_vertically( - rs[i]) && - resolve_references.is_in_viewport_horizontally( - rs[i])) { - logger.debug("processing single references", rs); - $(rs[i]).toggleClass(_unresolved_class_name, false); - - // discard return value as it is not needed for any summary - // generation as above. - resolve_references.update_single_resolvable_reference(rs[i]); - } - } - } - } -} - - -$(document).ready(function () { - if ("${BUILD_MODULE_EXT_RESOLVE_REFERENCES}" === "ENABLED") { - caosdb_modules.register(resolve_references); - } -}); + });