--- regenerate: true --- {% capture cache %} {% comment %} # ----------------------------------------------------------------------------- # ~/assets/themes/j1/adapter/js/themer.js # Liquid template to adapt theme functions # # Product/Info: # https://jekyll.one # # Copyright (C) 2023 Juergen Adams # # J1 Theme is licensed under the MIT License. # For details, see: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE.md # # ----------------------------------------------------------------------------- # 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/themes/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 themer_defaults = modules.defaults.themer.defaults %} {% assign themer_settings = modules.themer.settings %} {% assign footer_defaults = blocks.defaults.footer.defaults %} {% assign footer_settings = blocks.footer.settings %} {% comment %} Set config options -------------------------------------------------------------------------------- {% endcomment %} {% assign themer_options = themer_defaults| merge: themer_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/themes/j1/adapter/js/themer.js # JS Adapter for J1 themer (bootstrapThemeSwitcher) # # Product/Info: # https://jekyll.one # https://github.com/jguadagno/bootstrapThemeSwitcher # # Copyright (C) 2023 Juergen Adams # Copyright (C) 2014 Joseph Guadagno # # J1 Theme is licensed under the MIT License. # For details, see: https://github.com/jekyll-one-org/j1-template/blob/main/LICENSE.md # bootstrapThemeSwitcher is licensed under the MIT License. # For details, see https://github.com/jguadagno/bootstrapThemeSwitcher/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.themer = (function (j1, window) { // --------------------------------------------------------------------------- // globals // --------------------------------------------------------------------------- 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 user_state_detected = false; 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 _this; var logger; var logText; var cookie_written; var themerDefaults; var themerSettings; var themerOptions; var max_count; var j1Cookies; var gaCookies; var url; var baseUrl; var error_page; // --------------------------------------------------------------------------- // 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.themer', generated: '{{site.time}}' }, options); // ----------------------------------------------------------------------- // Global variable settings // ----------------------------------------------------------------------- _this = j1.adapter.themer; logger = log4javascript.getLogger('j1.adapter.themer'); // Load module DEFAULTS|CONFIG themerDefaults = $.extend({}, {{themer_defaults | replace: 'nil', 'null' | replace: '=>', ':' }}); themerSettings = $.extend({}, {{themer_settings | replace: 'nil', 'null' | replace: '=>', ':' }}); themerOptions = $.extend(true, {}, themerDefaults, themerSettings); max_count = themerOptions.retries; url = new liteURL(window.location.href); baseUrl = url.origin; error_page = url.origin + '/204.html'; j1Cookies = j1.findCookie('j1'); gaCookies = j1.findCookie('__g'); // initialize state flag _this.state = 'started'; if (development) { logger.debug('\n' + 'state: ' + _this.getState()); } // hide page until 'theme' is loaded $('#no_flicker').hide(); // 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) var dependencies_met_user_state_available = setInterval (function () { user_state_detected = 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 (user_state_detected) { user_state = j1.readCookie(cookie_names.user_state); user_consent = j1.readCookie(cookie_names.user_consent); if (development) { logger.debug('\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) { if (development) { logger.error('\n' + 'failed to write cookie: ' + cookie_names.user_consent); } } } // set the theme switcher state user_state.theme_switcher = themerOptions.enabled; if (themerOptions.enabled) { // enable BS ThemeSwitcher if (development) { logger.info('\n' + 'themes detected as: ' + themerOptions.enabled); logger.info('\n' + 'remote themes are being initialized'); } /* eslint-disable */ // load list of remote themes $('#remote_themes').bootstrapThemeSwitcher.defaults = { debug: themerOptions.debug, saveToCookie: themerOptions.saveToCookie, cssThemeLink: themerOptions.cssThemeLink, cookieThemeName: themerOptions.cookieThemeName, cookieDefaultThemeName: themerOptions.cookieDefaultThemeName, cookieThemeCss: themerOptions.cookieThemeCss, cookieThemeExtensionCss: themerOptions.cookieThemeExtensionCss, cookieExpiration: themerOptions.cookieExpiration, cookiePath: themerOptions.cookiePath, defaultCssFile: themerOptions.defaultCssFile, bootswatchApiUrl: themerOptions.bootswatchApiUrl, bootswatchApiVersion: themerOptions.bootswatchApiVersion, loadFromBootswatch: themerOptions.loadFromBootswatch, localFeed: themerOptions.localThemes, excludeBootswatch: themerOptions.excludeBootswatch, includeBootswatch: themerOptions.includeBootswatch, skipIncludeBootswatch: themerOptions.skipIncludeBootswatch }; /* eslint-enable */ } else { if (development) { logger.warn('\n' + 'themes detected as: disabled'); logger.warn('\n' + 'no remote themes are available'); } } // 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 if (development) { logger.warn('\n' + 'themes CSS invalid: ' + user_state.theme_css); } theme_css_html = ''; if (development) { logger.warn('\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_user_state_available); } }, 10); // END dependencies_met_user_state_available // set final module state if theme loaded var dependencies_met_theme_applied = setInterval (function () { user_state = j1.readCookie(cookie_names.user_state); styleLoaded = styleSheetLoaded(user_state.theme_css); if (styleLoaded) { // show page (theme is loaded) $('#no_flicker').show(); if (development) { logger.info('\n' + 'theme loaded successfully: ' + user_state.theme_name); logger.debug('\n' + 'theme CSS loaded: ' + user_state.theme_css); } _this.setState('finished'); if (development) { logger.debug('\n' + 'state: ' + _this.getState()); logger.info('\n' + 'module initialized successfully'); } clearInterval(dependencies_met_theme_applied); } }, 10); // END dependencies_met_theme_applied }, // END init // ------------------------------------------------------------------------- // messageHandler // Manage messages send from other J1 modules // ------------------------------------------------------------------------- messageHandler: function (sender, message) { var json_message = JSON.stringify(message, undefined, 2); logText = '\n' + 'received message from ' + sender + ': ' + json_message; if (development) { logger.info(logText); } // ----------------------------------------------------------------------- // Process commands|actions // ----------------------------------------------------------------------- if (message.type === 'command' && message.action === 'module_initialized') { if (development) { logger.info('\n' + message.text); } // // Place handling of other command|action here // } }, // END messageHandler // ------------------------------------------------------------------------- // setState() // Sets the current (processing) state of the module // ------------------------------------------------------------------------- setState: function (stat) { _this.state = stat; }, // END setState // ------------------------------------------------------------------------- // getState() // Returns the current (processing) state of the module // ------------------------------------------------------------------------- getState: function () { return _this.state; } // END getState }; // END return })(j1, window); {% endcapture %} {% if production %} {{cache| minifyJS }} {% else %} {{cache| strip_empty_lines }} {% endif %} {% assign cache = nil %}