--- regenerate: true --- {%- capture cache -%} {% comment %} # ----------------------------------------------------------------------------- # ~/assets/theme/j1/adapter/js/themes.js # Liquid template to adapt theme functions # # Product/Info: # https://jekyll.one # # Copyright (C) 2023, 2024 Juergen Adams # # J1 Template is licensed under the MIT License. # For details, see: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE # # ----------------------------------------------------------------------------- # Test data: # {{config| debug }} # ----------------------------------------------------------------------------- {% endcomment %} {% comment %} Liquid procedures -------------------------------------------------------------------------------- {% endcomment %} {% comment %} Set global settings -------------------------------------------------------------------------------- {% endcomment %} {% assign environment = site.environment %} {% assign template_version = site.version %} {% assign asset_path = "/assets/theme/j1" %} {% comment %} Process YML config data ================================================================================ {% endcomment %} {% comment %} Set config files -------------------------------------------------------------------------------- {% endcomment %} {% assign template_config = site.data.j1_config %} {% assign blocks = site.data.blocks %} {% assign modules = site.data.modules %} {% comment %} Set config data -------------------------------------------------------------------------------- {% endcomment %} {% assign themes_defaults = modules.defaults.themes.defaults %} {% assign themes_settings = modules.themes.settings %} {% assign footer_defaults = blocks.defaults.footer.defaults %} {% assign footer_settings = blocks.footer.settings %} {% comment %} Set config options -------------------------------------------------------------------------------- {% endcomment %} {% assign themes_options = themes_defaults| merge: themes_settings %} {% assign footer_options = footer_defaults | merge: footer_settings %} {% assign footer = 'active_footer' %} {% assign footer_id = footer_options.active_footer %} {% assign default_theme = template_config.theme %} {% assign theme_base = "core/css/themes" %} {% comment %} Detect prod mode -------------------------------------------------------------------------------- {% endcomment %} {% if environment == "development" or environment == "test" %} {% assign theme_ext = "css" %} {% else %} {% assign theme_ext = "min.css" %} {% endif %} {% assign production = false %} {% if environment == 'prod' or environment == 'production' %} {% assign production = true %} {% endif %} /* # ----------------------------------------------------------------------------- # ~/assets/theme/j1/adapter/js/themes.js # JS Adapter for J1 themes (ThemeSwitcher) # # Product/Info: # https://jekyll.one # https://github.com/jguadagno/ThemeSwitcher # # Copyright (C) 2023, 2024 Juergen Adams # Copyright (C) 2014 Joseph Guadagno # # J1 Template is licensed under the MIT License. # For details, see: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE # ThemeSwitcher is licensed under the MIT License. # For details, see https://github.com/jguadagno/ThemeSwitcher/blob/master/LICENSE # ----------------------------------------------------------------------------- # NOTE: # Setup of theme loaders for local_themes|remote_themes moved # to adapter navigator.js # ----------------------------------------------------------------------------- # Adapter generated: {{site.time}} # ----------------------------------------------------------------------------- */ // ----------------------------------------------------------------------------- // ESLint shimming // ----------------------------------------------------------------------------- /* eslint indent: "off" */ /* eslint quotes: "off" */ // ----------------------------------------------------------------------------- "use strict"; j1.adapter.themes = (function (j1, window) { {% comment %} Set global variables ------------------------------------------------------------------------------ {% endcomment %} var environment = '{{environment}}'; var development = (environment.includes('dev') ? true : false); var url = new liteURL(window.location.href); var secure = (url.protocol.includes('https')) ? true : false; var user_state = {}; var user_consent = {}; var cookie_names = j1.getCookieNames(); var styleLoaded = false; var id = 'default'; var state = 'not_started'; var cssExtension = (development) ? '.css' : '.min.css'; var default_theme_name = '{{default_theme.name}}'; var default_theme_author = '{{default_theme.author}}'; var default_theme_author_url = '{{default_theme.author_url}}'; var default_theme_css_name = default_theme_name.toLowerCase(); var default_theme_css = '{{asset_path}}/{{theme_base}}/' + default_theme_css_name + '/bootstrap' + cssExtension; var interval_count = 0; var user_state_cookie; var theme_css_html; var cookie_written; var themesDefaults; var themesSettings; var themesOptions; var max_count; var j1Cookies; var gaCookies; var url; var baseUrl; var error_page; var _this; var logger; var logText; // date|time var startTime; var endTime; var startTimeModule; var endTimeModule; var timeSeconds; // --------------------------------------------------------------------------- // helper functions // --------------------------------------------------------------------------- function styleSheetLoaded(styleSheet) { var sheets = document.styleSheets, stylesheet = sheets[(sheets.length - 1)]; // find CSS file 'styleSheetName' in document for (var i in document.styleSheets) { if(sheets[i].href && sheets[i].href.indexOf(styleSheet) > -1) { return true; } } return false; } // see: https://stackoverflow.com/questions/4301968/checking-a-url-in-jquery-javascript // see: https://stackoverflow.com/questions/16481598/prevent-unhandled-jquery-ajax-error // var urlExists = function (url, callback) { if ( ! $.isFunction (callback)) { throw Error('Not a valid callback'); } $.ajax({ type: 'HEAD', url: url, success: $.proxy(callback, this, true), error: $.proxy(callback, this, false) }); }; // --------------------------------------------------------------------------- // Main object // --------------------------------------------------------------------------- return { // ------------------------------------------------------------------------- // initializer // ------------------------------------------------------------------------- init: function (options) { // ----------------------------------------------------------------------- // Default module settings // ----------------------------------------------------------------------- var settings = $.extend({ module_name: 'j1.adapter.themes', generated: '{{site.time}}' }, options); // ----------------------------------------------------------------------- // Global variable settings // ----------------------------------------------------------------------- _this = j1.adapter.themes; logger = log4javascript.getLogger('j1.adapter.themes'); // Load module DEFAULTS|CONFIG themesDefaults = $.extend({}, {{themes_defaults | replace: 'nil', 'null' | replace: '=>', ':' }}); themesSettings = $.extend({}, {{themes_settings | replace: 'nil', 'null' | replace: '=>', ':' }}); themesOptions = $.extend(true, {}, themesDefaults, themesSettings); max_count = themesOptions.retries; url = new liteURL(window.location.href); baseUrl = url.origin; error_page = url.origin + '/204.html'; j1Cookies = j1.findCookie('j1'); gaCookies = j1.findCookie('__g'); // jadams, 2023-06-10: Added to optimze 'CLS' of a page load. // Find conterpart (show) in the j1.adapter // hide content|footer until 'page' is loaded // // $('#content').hide(); // $('.{{footer}}').hide(); // jadams, 2021-07-25: problem seems NOT an timing issue on the iPad // platform. (General) Dependency should be REMOVED!!! // TODO: Isolate redirect for iPad ONLY!!! // // jadams, 2021-07-11: added dependecy on the user state cookie // Found timing issues testing mobile devices (iPad) // // ----------------------------------------------------------------------- // module initializer // ----------------------------------------------------------------------- var dependencies_met_page_ready = setInterval (() => { var pageState = $('#content').css("display"); // var pageState = $('#no_flicker').css("display"); var pageVisible = (pageState === 'block') ? true : false; var j1CoreFinished = (j1.getState() === 'finished') ? true : false; // var atticFinished = (j1.adapter.attic.getState() === 'finished') ? true: false; // var userStateDetected = j1.existsCookie(cookie_names.user_state); // counter how often the check should be done for the existence // of the user state cookie // interval_count += 1; if (pageVisible && j1CoreFinished) { startTimeModule = Date.now(); user_state = j1.readCookie(cookie_names.user_state); user_consent = j1.readCookie(cookie_names.user_consent); _this.setState('started'); logger.debug('\n' + 'state: ' + _this.getState()); logger.info('\n' + 'module is being initialized'); // hide page until 'theme' is loaded logger.info('\n' + 'hide page until theme is loaded'); $('#no_flicker').hide(); // logger.info('\n' + 'cookie ' + cookie_names.user_state + ' successfully loaded after: ' + interval_count * 25 + ' ms'); // initial theme data if (user_state.theme_css === '') { user_state.theme_name = default_theme_name; user_state.theme_css = default_theme_css; user_state.theme_author = default_theme_author; user_state.theme_author_url = default_theme_author_url; cookie_written = j1.writeCookie({ name: cookie_names.user_state, data: user_state, secure: secure, expires: 365 }); if (!cookie_written) { logger.error('\n' + 'failed to write cookie: ' + cookie_names.user_consent); } } // END if user_state theme_css === '' // set the theme switcher state user_state.theme_switcher = themesOptions.enabled; if (themesOptions.enabled) { // enable BS ThemeSwitcher logger.info('\n' + 'themes detected as: ' + themesOptions.enabled); logger.info('\n' + 'remote themes are being initialized'); /* eslint-disable */ // load list of remote themes $('#remote_themes').ThemeSwitcher.defaults = { debug: themesOptions.debug, saveToCookie: themesOptions.saveToCookie, cssThemeLink: themesOptions.cssThemeLink, cookieThemeName: themesOptions.cookieThemeName, cookieDefaultThemeName: themesOptions.cookieDefaultThemeName, cookieThemeCss: themesOptions.cookieThemeCss, cookieThemeExtensionCss: themesOptions.cookieThemeExtensionCss, cookieExpiration: themesOptions.cookieExpiration, cookiePath: themesOptions.cookiePath, defaultCssFile: themesOptions.defaultCssFile, bootswatchApiUrl: themesOptions.bootswatchApiUrl, bootswatchApiVersion: themesOptions.bootswatchApiVersion, loadFromBootswatch: themesOptions.loadFromBootswatch, localFeed: themesOptions.localThemes, excludeBootswatch: themesOptions.excludeBootswatch, includeBootswatch: themesOptions.includeBootswatch, skipIncludeBootswatch: themesOptions.skipIncludeBootswatch }; /* eslint-enable */ } else { logger.debug('\n' + 'themes detected as: disabled'); logger.debug('\n' + 'no remote themes are available'); } // END if themesOptions enabled // validate theme to be loaded urlExists(user_state.theme_css, function(success) { // load theme if (success) { // continue processing if page is ready var dependencies_met_theme_loaded = setInterval (function () { if (j1.getState() == 'finished') { theme_css_html = ''; $('head').append(theme_css_html); clearInterval(dependencies_met_theme_loaded); } }, 10); // END dependencies_met_theme_loaded } else { // invalid theme, fallback on default logger.warn('\n' + 'themes CSS invalid: ' + user_state.theme_css); theme_css_html = ''; logger.debug('\n' + 'set default theme :' + default_theme_name); logger.debug('\n' + 'theme CSS loaded: ' + default_theme_css); $('head').append(theme_css_html); // write theme defaults to cookie user_state.theme_name = default_theme_name; user_state.theme_css = default_theme_css; user_state.theme_author = default_theme_author; user_state.theme_author_url = default_theme_author_url; cookie_written = j1.writeCookie({ name: cookie_names.user_state, data: user_state, secure: secure, expires: 365 }); if (!cookie_written) { logger.error('\n' + 'failed to write cookie: ' + cookie_names.user_consent); } // reload page using the default thme location.reload(true); } }); clearInterval(dependencies_met_page_ready); } }, 10); // END dependencies_met_page_ready // set final module state if theme loaded var dependencies_met_theme_applied = setInterval (() => { user_state = j1.readCookie(cookie_names.user_state); styleLoaded = styleSheetLoaded(user_state.theme_css); if (styleLoaded) { // show page (theme is loaded) logger.info('\n' + 'theme loaded successfully: ' + user_state.theme_name); logger.debug('\n' + 'theme CSS loaded: ' + user_state.theme_css); logger.info('\n' + 'show page on theme loaded'); $('#no_flicker').show(); _this.setState('finished'); logger.debug('\n' + 'state: ' + _this.getState()); logger.info('\n' + 'initializing module finished'); endTimeModule = Date.now(); logger.info('\n' + 'module initializing time: ' + (endTimeModule-startTimeModule) + 'ms'); clearInterval(dependencies_met_theme_applied); } // ENF if styleLoaded }, 10); // END dependencies_met_theme_applied }, // END init // ------------------------------------------------------------------------- // messageHandler() // manage messages send from other J1 modules // ------------------------------------------------------------------------- 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 // ----------------------------------------------------------------------- if (message.type === 'command' && message.action === 'module_initialized') { // // place handling of command|action here // logger.info('\n' + message.text); } // // place handling of other command|action here // return true; }, // END messageHandler // ------------------------------------------------------------------------- // setState() // sets the current (processing) state of the module // ------------------------------------------------------------------------- setState: (stat) => { _this.state = stat; }, // END setState // ------------------------------------------------------------------------- // getState() // Returns the current (processing) state of the module // ------------------------------------------------------------------------- getState: () => { return _this.state; } // END getState }; // END main (return) })(j1, window); {%- endcapture -%} {%- if production -%} {{ cache|minifyJS }} {%- else -%} {{ cache|strip_empty_lines }} {%- endif -%} {%- assign cache = false -%}