assets/themes/j1/adapter/js/fab.js in j1-template-2024.1.5 vs assets/themes/j1/adapter/js/fab.js in j1-template-2024.2.0

- old
+ new

@@ -18,17 +18,10 @@ # For details, see: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE.md # ----------------------------------------------------------------------------- # Test data: # {{ liquid_var | debug }} # ----------------------------------------------------------------------------- - # NOTE: - # jadams, 2020-07-17: - # J1 FAB can't be minfied for now. Uglifier fails on an ES6 (most probably) - # structure that couldn't fixed by 'harmony' setting. Minifier fails by: - # Unexpected token: punc ()) - # Current, minifying has been disabled - # ----------------------------------------------------------------------------- {% endcomment %} {% comment %} Liquid var initialization -------------------------------------------------------------------------------- {% endcomment %} @@ -58,41 +51,44 @@ {% endif %} /* # ----------------------------------------------------------------------------- # ~/assets/themes/j1/adapter/js/fab.js - # JS Adapter for J1 FAB (Floating Action Button) + # JS Adapter for J1 FABs (Floating Action Buttons) # # Product/Info: # http://jekyll.one # # Copyright (C) 2023, 2024 Juergen Adams # # J1 Template is licensed under the MIT License. # For details, see http://jekyll.one # ----------------------------------------------------------------------------- + # TODO: check why 'found toc in page: disabled' detected (some times) + # if a toc IS configured + # ----------------------------------------------------------------------------- # Adapter generated: {{site.time}} # ----------------------------------------------------------------------------- */ // ----------------------------------------------------------------------------- // ESLint shimming // ----------------------------------------------------------------------------- /* eslint indent: "off" */ // ----------------------------------------------------------------------------- 'use strict'; -j1.adapter.fab = (function (j1, window) { +j1.adapter.fab = ((j1, window) => { // --------------------------------------------------------------------------- - // Global variable settings + // global variable settings // --------------------------------------------------------------------------- - var isMobile = j1.core.isMobile(); - var environment = '{{environment}}'; - var dclFinished = false; - var moduleOptions = {}; - var cookie_names = j1.getCookieNames(); - var state = 'not_started'; + var isMobile = j1.core.isMobile(); + var environment = '{{environment}}'; + var dclFinished = false; + var moduleOptions = {}; + var cookie_names = j1.getCookieNames(); + var state = 'not_started'; var fabDefaults; var fabSettings; var fabOptions; var frontmatterOptions; var user_state; @@ -100,80 +96,92 @@ var user_data; var sect1Nodes; var sect3Nodes; var sect12Nodes; var sect123Nodes; + var _this; var logger; var logText; + // date|time + var startTime; + var endTime; + var startTimeModule; + var endTimeModule; + var timeSeconds; + // --------------------------------------------------------------------------- // helper functions // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- - // main object + // main // --------------------------------------------------------------------------- return { // ------------------------------------------------------------------------- - // module initializer + // adapter initializer // ------------------------------------------------------------------------- - init: function (options) { + init: (options) => { // ----------------------------------------------------------------------- - // Default module settings + // default module settings // ----------------------------------------------------------------------- var settings = $.extend({ module_name: 'j1.adapter.fab', generated: '{{site.time}}' }, options); // ----------------------------------------------------------------------- - // Global variable settings + // global variable settings // ----------------------------------------------------------------------- - _this = j1.adapter.fab; - logger = log4javascript.getLogger('j1.adapter.fab'); - sect123Nodes = $('[class$="sect1"],[class$="sect2"],[class$="sect3"]'); - sect12Nodes = $('[class$="sect1"],[class$="sect2"]'); - sect1Nodes = $('[class$="sect1"]'); + _this = j1.adapter.fab; + logger = log4javascript.getLogger('j1.adapter.fab'); + sect123Nodes = $('[class$="sect1"],[class$="sect2"],[class$="sect3"]'); + sect12Nodes = $('[class$="sect1"],[class$="sect2"]'); + sect1Nodes = $('[class$="sect1"]'); - // initialize state flag - _this.setState('started'); - logger.info('\n' + 'set module state to: ' + _this.getState()); - logger.info('\n' + 'module is being initialized'); - // create settings object from frontmatter (page settings) frontmatterOptions = options != null ? $.extend({}, options) : {}; // Load module DEFAULTS|CONFIG fabDefaults = $.extend({}, {{fab_defaults | replace: 'nil', 'null' | replace: '=>', ':' }}); fabSettings = $.extend({}, {{fab_settings | replace: 'nil', 'null' | replace: '=>', ':' }}); fabOptions = $.extend(true, {}, fabDefaults, fabSettings, frontmatterOptions); // save config settings into the FAB object for global access - // _this['moduleOptions'] = fabOptions; - var dependencies_met_navigator = setInterval(function() { - var pageState = $('#no_flicker').css("display"); - var pageVisible = (pageState == 'block') ? true : false; + // ----------------------------------------------------------------------- + // module initializer + // ----------------------------------------------------------------------- + var dependency_met_page_ready = setInterval(() => { + var pageState = $('#content').css("display"); + var pageVisible = (pageState === 'block') ? true : false; + var j1CoreFinished = (j1.getState() === 'finished') ? true : false; + var atticFinished = (j1.adapter.attic.getState() === 'finished') ? true: false; - if (j1.adapter.navigator.getState() == 'finished' && pageVisible) { + if (pageVisible && j1CoreFinished && atticFinished) { + startTimeModule = Date.now(); - logger.debug('\n' + 'met dependencies for: navigator'); + _this.setState('started'); + logger.info('\n' + 'set module state to: ' + _this.getState()); + logger.info('\n' + 'module is being initialized'); + + logger.info('\n' + 'load FABs'); _this.fabLoader(fabOptions); - clearInterval(dependencies_met_navigator); - } - }, 10); + clearInterval(dependency_met_page_ready); + } // END pageVisible + }, 10); // END dependency_met_page_ready }, // END init // ------------------------------------------------------------------------- // FAB Loader // ------------------------------------------------------------------------- - fabLoader: function (fabOptions) { + fabLoader: (fabOptions) => { _this.setState('loading'); logger.info('\n' + 'set module state to: ' + _this.getState()); logger.info('\n' + 'load HTML data for FAB: ' + fabOptions.fab_menu_id); @@ -187,104 +195,103 @@ ); // --------------------------------------------------------------------- // Initialize FAB button // --------------------------------------------------------------------- - var dependencies_met_fab_initialized = setInterval (function () { - var pageState = $('#no_flicker').css("display"); - var pageVisible = (pageState == 'block') ? true: false; - var atticFinished = (j1.adapter.attic.getState() == 'finished') ? true: false; + var dependencies_met_fab_initialized = setInterval (() => { + var fabLoaded = (j1.xhrDOMState['#' + fabOptions.xhr_container_id] === 'success') ? true: false; - if (j1.xhrDOMState['#' + fabOptions.xhr_container_id] == 'success' && j1.getState() == 'finished' && pageVisible ) { + if (fabLoaded) { _this.setState('loaded'); logger.info('\n' + 'set module state to: ' + _this.getState()); logger.info('\n' + 'HTML data for FAB: ' + _this.getState()); _this.buttonInitializer(fabOptions); + $('.fab-btn').show(); _this.setState('finished'); logger.debug('\n' + 'state: ' + _this.getState()); logger.info('\n' + 'module initialized successfully'); - $('.fab-btn').show(); + endTimeModule = Date.now(); + logger.info('\n' + 'module initializing time: ' + (endTimeModule-startTimeModule) + 'ms'); clearInterval(dependencies_met_fab_initialized); - } + } // END if fabLoaded }, 10); // END dependencies_met_fab_initialized - }, // END dataLoader + }, // END fabLoader // ------------------------------------------------------------------------- - // Button Initializer + // buttonInitializer() // ------------------------------------------------------------------------- - buttonInitializer: function (fabOptions) { + buttonInitializer: (fabOptions) => { + var $fabContainer = $('#' + fabOptions.xhr_container_id); + var iconFamily = fabOptions.icon_family.toLowerCase(); + var floatingActionOptions = fabOptions.menu_options; + var fabButtons = document.querySelectorAll('.fab-btn'); var eventHandler; var actionMenuId; var actionMenuOptions; var actionButtonId; var instances; var $actionButton; var toggleIcons; var fabActions; - var $fabContainer = $('#' + fabOptions.xhr_container_id); - var iconFamily = fabOptions.icon_family.toLowerCase(); - var floatingActionOptions = fabOptions.menu_options; - var fabButtons = document.querySelectorAll('.fab-btn'); // check if multiple buttons detected - if ( fabButtons.length == 1 ) { + if (fabButtons.length === 1) { _this.setState('processing'); logger.info('\n' + 'set module state to: ' + _this.getState()); logger.info('\n' + 'initialize FAB menu'); actionButtonId = fabButtons[0].firstElementChild.id; actionMenuId = actionButtonId.replace('_button', ''); instances = j1.fab.init(fabButtons, floatingActionOptions); $actionButton = $('#' + actionButtonId); - fabOptions.menus.forEach(function (menu, index) { + fabOptions.menus.forEach((menu, index) => { if (menu.id === actionMenuId) { actionMenuOptions = fabOptions.menus[index]; }; }); // count number of menu actions for the button. If only one action // found the FAB button gets created as a FAB (no menu) that has the // the action bound directly to the button // - fabActions = actionMenuOptions.items.length; + fabActions = actionMenuOptions.items.length; toggleIcons = iconFamily + '-' + actionMenuOptions.icon + ' ' + iconFamily + '-' + actionMenuOptions.icon_hover; // toggle the icon for the FAB if configured if (floatingActionOptions.hoverEnabled) { $actionButton.hover( - function() { + function () { $('#fab-icon').toggleClass(toggleIcons); - }, function() { + }, function () { $('#fab-icon').toggleClass(toggleIcons); } ); } else { - $actionButton.on('click', function (e) { + $actionButton.on('click', (e) => { $('#fab-icon').toggleClass(toggleIcons); }); } if (fabActions > 1) { - - actionMenuOptions.items.forEach(function (item, index) { + actionMenuOptions.items.forEach((item, index) => { // Bind an eventhandler instance if item id exists if ($('#' + item.id).length) { eventHandler = item.event_handler; // check if eventhandler configured is a SINGLE word if (eventHandler.split(' ').length == 1) { - logger.info('\n' + 'register pre-configured eventhandler ' +eventHandler+ ' on id: #' + item.id); + logger.debug('\n' + 'register pre-configured eventhandler ' + eventHandler + ' on id: #' + item.id); - if ( eventHandler === 'open_mmenu_toc' ) { + if (eventHandler === 'open_mmenu_toc') { if ($('#j1-toc-mgr').length) { logger.info('\n' + 'found toc in page: enabled'); - var dependencies_met_toccer_finished = setInterval (function () { - if ( j1.adapter.toccer.getState() == 'finished' ) { + var dependencies_met_toccer_finished = setInterval (() => { + if (j1.adapter.toccer.getState() == 'finished') { logger.debug('\n' + 'met dependencies for: toccer'); $('#open_mmenu_toc').show(); clearInterval(dependencies_met_toccer_finished); } @@ -294,13 +301,13 @@ } } else { $('#' + item.id).show(); } // END eventHandler 'open_mmenu_toc' - $('#' + item.id).each(function(e) { + $('#' + item.id).each(function (e) { var $this = $(this); - $this.on('click', function(e) { + $this.on('click', function (e) { _this[item.event_handler](sect123Nodes); }); }); } else { logger.info('\n' + 'register custom eventhandler on id: #' + item.id); @@ -314,19 +321,19 @@ logger.info('\n' + 'single action found for FAB, no menu loaded/created'); // disable hover event (CSS) // $actionButton.css({'pointer-events': 'none'}) - actionMenuOptions.items.forEach(function (item, index) { + actionMenuOptions.items.forEach((item, index) => { eventHandler = item.event_handler; // check if eventhandler configured is a SINGLE word - if (eventHandler.split(' ').length == 1) { - logger.info('\n' + 'register pre-configured eventhandler ' +eventHandler+ ' on id: #' + actionButtonId); + if (eventHandler.split(' ').length === 1) { + logger.debug('\n' + 'register pre-configured eventhandler ' +eventHandler+ ' on id: #' + actionButtonId); if (eventHandler === 'scroll_to_top') { // register click event - $actionButton.on('click', function(e) { + $actionButton.on('click', function (e) { var dest = 0; $('html, body').animate({ scrollTop: dest }, 500); }); @@ -334,12 +341,12 @@ if ( eventHandler === 'open_mmenu_toc' ) { // check if toccer (toc_mgr) is available if ($('#j1-toc-mgr').length) { logger.info('\n' + 'found toc in page: enabled'); - var dependencies_met_toccer_finished = setInterval (function () { - if ( j1.adapter.toccer.getState() == 'finished' ) { + var dependencies_met_toccer_finished = setInterval (() => { + if (j1.adapter.toccer.getState() === 'finished') { logger.debug('\n' + 'met dependencies for toccer: finished'); // change the id of the $actionButton to the already // registered id by mmenu adapter of ('open_mmenu_toc') // to open the TOC sidebar @@ -362,36 +369,40 @@ $fabContainer.hide(); } // END if famButton }, // END buttonInitializer // ------------------------------------------------------------------------- - // Eventhandler + // event handler + // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- - // open mmenu TOC + // open_mmenu_toc() + // open TOC in mobile menu // ------------------------------------------------------------------------- - open_mmenu_toc: function () { + open_mmenu_toc: () => { // Event configured with Navigator module (navigator.yml) // with content section DRAWER TOC. Event registered at // runtime on element with id '#open_mmenu_toc' by Mobile Menu // module ADAPTER (mmenu.js) // // NOTE: no further handling needed for this event }, // END open_mmenu_toc // ------------------------------------------------------------------------- - // reload page + // reload_page() + // reload current page // ------------------------------------------------------------------------- - reload_page: function () { + reload_page: () => { // reload current page (skip cache) location.reload(true); }, // END reload_page // ------------------------------------------------------------------------- - // scroll to previous section + // scroll_previous_section() + // scroll to previous section in page // ------------------------------------------------------------------------- - scroll_previous_section: function (nodes) { + scroll_previous_section: (nodes) => { var previous_header_id; var currentNode; var prev_node; var anchor_id; var index = 0; @@ -399,11 +410,11 @@ var $toc = $('#sidebar'); var current_header_id = $toc.find('.is-active-link').attr('href'); var toccerScrollDuration = {{toccer_options.scrollSmoothDuration}}; var toccerScrollOffset = {{toccer_options.scrollSmoothOffset}}; - // Scroll offset correction if mobile or window width <= 992 + // scroll offset correction if mobile or window width <= 992 // For smaller window sizes, the height of the menubar changes. // if (j1.core.isMobile() || $(window).width() <= 992) { scrollOffset += 30; } // calculate offset for correct (smooth) scroll position. // var $pagehead = $('.attic'); @@ -423,11 +434,11 @@ // static offset, to be checked why this is needed // scrollOffset = scrollOffset + toccerScrollOffset; - nodes.each(function () { + nodes.each(() => { currentNode = $(this).find(current_header_id); if (currentNode.length) { if (index > maxNode) { return false; } else { @@ -445,13 +456,14 @@ (index < maxNode) ? index++ : index; }); }, // END scroll_previous_section // ------------------------------------------------------------------------- - // scroll to next section + // scroll_next_section() + // scroll to next section in page // ------------------------------------------------------------------------- - scroll_next_section: function (nodes) { + scroll_next_section: (nodes) => { var next_header_id; var next_header_plus_id; var currentNode; var current_header_id; var nextNode; @@ -463,11 +475,11 @@ var scrollDuration = {{toccer_options.scrollSmoothDuration}}; var toccerScrollDuration = {{toccer_options.scrollSmoothDuration}}; var toccerScrollOffset = {{toccer_options.scrollSmoothOffset}}; current_header_id = $toc.find('.is-active-link').attr('href'); - nodes.each(function () { + nodes.each(() => { currentNode = $(this).find(current_header_id); if (currentNode.length) { if (index == maxNode) { return false; } else { @@ -506,26 +518,28 @@ index < maxNode ? index++ : index; }); }, // END scroll_next_section // ------------------------------------------------------------------------- - // scroll to top + // scroll_to_top() + // scroll to top of current pqge // ------------------------------------------------------------------------- - scroll_to_top: function () { + scroll_to_top: () => { var dest = 0; $('html, body').animate({ scrollTop: dest }, 500); // tocbot.refresh(); }, // END scroll_top // ------------------------------------------------------------------------- - // scroll to bottom + // scroll_to_bottom() + // scroll to bottom of current page // ------------------------------------------------------------------------- - scroll_to_bottom: function () { + scroll_to_bottom: () => { var $page = $(document); var $footer = $('#j1_footer'); var f = $footer.length ? $footer.outerHeight() : 0; var pageHeight = $page.height() - f - 400; var pageHeightOuter = $page.outerHeight(); @@ -536,69 +550,69 @@ // tocbot.refresh(); }, // END scroll_bottom // ------------------------------------------------------------------------- - // scroll to comments (Disqus) + // scroll_to_comments() + // scroll to comments headline in current page (if comments enabled) // ------------------------------------------------------------------------- - scroll_to_comments: function () { + scroll_to_comments: () => { }, // END scroll_comments // ------------------------------------------------------------------------- + // alert_me() // create generic alert // ------------------------------------------------------------------------- - alert_me: function () { + alert_me: () => { alert ('Hello world!'); }, // END alert_me // ------------------------------------------------------------------------- - // messageHandler - // Manage messages (paylods) send from other J1 modules + // messageHandler() + // manage messages send from other J1 modules // ------------------------------------------------------------------------- - messageHandler: function (sender, message) { - // var json_message = JSON.stringify(message, undefined, 2); // multiline - var json_message = JSON.stringify(message); + messageHandler: (sender, message) => { + var json_message = JSON.stringify(message, undefined, 2); logText = '\n' + 'received message from ' + sender + ': ' + json_message; logger.debug(logText); // ----------------------------------------------------------------------- - // Process commands|actions + // process commands|actions // ----------------------------------------------------------------------- if (message.type === 'command' && message.action === 'module_initialized') { + // - // Place handling of command|action here + // place handling of command|action here // + logger.info('\n' + message.text); } - if (message.type === 'command' && message.action === 'status') { - logger.info('\n' + 'messageHandler: received - ' + message.action); - } // - // Place handling of other command|action here + // place handling of other command|action here // return true; }, // END messageHandler // ------------------------------------------------------------------------- // setState() - // Sets the current (processing) state of the module + // sets the current (processing) state of the module // ------------------------------------------------------------------------- - setState: function (stat) { + setState: (stat) => { _this.state = stat; }, // END setState // ------------------------------------------------------------------------- // getState() // Returns the current (processing) state of the module // ------------------------------------------------------------------------- - getState: function () { + getState: () => { return _this.state; } // END getState - }; // END return + }; // END main (return) })(j1, window); {% endcapture %} {% if production %} {{ cache | minifyJS }}