diff --git a/ext_cosmetics.js b/ext_cosmetics.js index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..08c5e0e235372451b2a6b66cdb7747953b08f066 100644 --- a/ext_cosmetics.js +++ b/ext_cosmetics.js @@ -0,0 +1,175 @@ +/* + * This file is a part of the LinkAhead Project. + * + * Copyright (C) 2021-2024 IndiScale GmbH <info@indiscale.com> + * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com> + * Copyright (C) 2023 Florian Spreckelsen <f.spreckelsen@indiscale.com> + * Copyright (C) 2023 Daniel Hornung <d.hornung@indiscale.com> + * Copyright (C) 2024 Joscha Schmiedt <joscha@schmiedt.dev> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +"use strict"; + +/** + * Cosmetics module is a collection of small look-and-feel tweaks for the + * LinkAhead webui. + * + * @author Timm Fitschen + */ +var cosmetics = new function () { + + /** + * Cut-off length of links. When linkify processes the links any href + * longer than this will be cut off at the end and "[...]" will be + * appended for the link text. + */ + var _link_cut_off_length = 40; + + var _custom_datetime = function () { + $('.caosdb-f-property-datetime-value').each(function (index) { + if (!($(this).hasClass("caosdb-v-property-datetime-customized"))) { + var result = this.innerText.replace(/T/, " ").replace(/\+.*/, ""); + result = `<span class="caosdb-v-property-datetime-customized-newvalue">${result}</span>`; + + // add class to highlight that this has been customized already + $(this).addClass("caosdb-v-property-datetime-customized") + $(this).hide(); + $(this).after(result); + } + }); + } + + /** + * Remove all the custom datetime elements again, for example when entering the edit mode. + */ + var _custom_datetime_clear = function () { + $('.caosdb-v-property-datetime-customized-newvalue').each(function () { + $(this).remove(); + } + ) + } + + /** + * Return a string with all occurences of a http(s) url in a given string replaced by <a> elements + * @param {string} text - The text to be searched for URLs + * @returns {string} text with <a> elements instead of raw links + */ + function linkify_string(text) { + // const match_url_regex = /https?:\/\/[^\s]*/g // original + // https://regexr.com helps you design regex + const match_url_regex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.?[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g + + return text.replace(match_url_regex, function (href) { + var link_text = href; + if (_link_cut_off_length > 4 && link_text.length > _link_cut_off_length) { + link_text = link_text.substring(0, _link_cut_off_length - 5) + "[...]"; + } + + return `<a title="Open ${href} in a new tab." target="_blank" class="caosdb-v-property-href-value" href="${href}">${link_text} <i class="bi bi-box-arrow-up-right"></i></a>`; + }); + } + + /** + * Turn all URLs in .caosdb-f-property-text-value DOM elements into actual links + */ + var _linkify_all_text_values = function () { + $('.caosdb-f-property-text-value').each(function (index) { + if (!($(this).hasClass("caosdb-v-property-linkified")) && (/https?:\/\//.test(this.innerText))) { + var linkified_text_value = linkify_string(this.innerText); + // add class to highlight that this has been linkified already + // (see https://gitlab.com/caosdb/caosdb-webui/-/issues/199). + $(this).addClass("caosdb-v-property-linkified") + $(this).hide(); + $(this).after(linkified_text_value); + } + }); + } + + /** + * Convert any substring of a text-value beginning with 'http(s)://' into a + * link. + * + * A listener detects edit-mode changes and previews + */ + var linkify = function () { + _linkify_all_text_values(); + + // edit-mode-listener + document.body.addEventListener(edit_mode.end_edit.type, _linkify_all_text_values, true); + // preview listener + document.body.addEventListener(preview.previewReadyEvent.type, _linkify_all_text_values, true); + } + + /** + * Customize datetime formatting. + * + * A listener detects edit-mode changes and previews + */ + var custom_datetime = function () { + _custom_datetime(); + + // edit-mode-listener to delete replacement + document.body.addEventListener(edit_mode.start_edit.type, _custom_datetime_clear, true); + // edit-mode-listener to recreate + document.body.addEventListener(edit_mode.end_edit.type, _custom_datetime, true); + // preview listener + document.body.addEventListener(preview.previewReadyEvent.type, _custom_datetime, true); + } + + /** + * Prettify double values for display purposes. + */ + const prettify_double_values = () => { + $('.caosdb-f-property-double-value').each(function (index) { + if (!$(this).hasClass("caosdb-v-property-double-prettified")) { + let value = parseFloat(this.innerText); + let prettified_value = ""; + + if (Math.abs(value) > 1e6 || Math.abs(value) < 1e-6) { + // Use scientific notation for very large or very small values + prettified_value = value.toExponential(1); + } else { + // Otherwise, display with up to 12 significant digits + prettified_value = value.toPrecision(12).replace(/\.?0+$/, ''); + } + + $(this).addClass("caosdb-v-property-double-prettified"); + $(this).hide(); + $(this).after(`<span class="caosdb-v-property-double-prettified-newvalue">${prettified_value}</span>`); + } + }); + }; + + this.init = function () { + this.custom_datetime = custom_datetime; + if ("${BUILD_MODULE_EXT_COSMETICS_CUSTOMDATETIME}" == "ENABLED") { + custom_datetime(); + } + this.linkify = linkify; + if ("${BUILD_MODULE_EXT_COSMETICS_LINKIFY}" == "ENABLED") { + linkify(); + } + this.prettify_double_values = prettify_double_values; + if ("${BUILD_MODULE_EXT_COSMETICS_PRETTIFY_DOUBLES}" === "ENABLED") { + prettify_double_values(); + } + } +} + + +$(document).ready(function () { + caosdb_modules.register(cosmetics); +});