From 5e62b093311e5fb9e19fe5f9605887ceadbfc5d5 Mon Sep 17 00:00:00 2001 From: George Cushen Date: Sun, 9 Feb 2020 00:10:45 +0000 Subject: [PATCH] fix: day/night mode and enable reverting to the default auto day/night mode Fixes: - There is no easy way for a user to reset their day/night preference back to automatic (currently, they must use their web browser to clear the local storage data for the site) - When changing the theme variation is disabled by admin (by setting `day_night` to `false` in `params.toml`), the operating system's day/night preference is still applied - If the admin removes the option to change the theme variation, the preference for a user who already visited the site is still read from the localstorage and applied. For example, this could result in the user seeing a theme variation with poor contrast that was not intended to be shown as the site's theme was optimized for the other variation. Fix #1385 Fix #1526 Fix #1534 --- assets/js/academic.js | 403 ++++++++++++++++++++++------------ layouts/partials/site_js.html | 9 +- 2 files changed, 275 insertions(+), 137 deletions(-) diff --git a/assets/js/academic.js b/assets/js/academic.js index 7fbbc1b0..b2d646e7 100644 --- a/assets/js/academic.js +++ b/assets/js/academic.js @@ -5,7 +5,7 @@ * Core JS functions and initialization. **************************************************/ -(function($){ +(function ($) { /* --------------------------------------------------------------------------- * Responsive scrolling for URL hashes. @@ -31,7 +31,7 @@ target = (typeof target === 'undefined' || typeof target === 'object') ? decodeURIComponent(window.location.hash) : target; // If target element exists, scroll to it taking into account fixed navigation bar offset. - if($(target).length) { + if ($(target).length) { // Escape special chars from IDs, such as colons found in Markdown footnote links. target = '#' + $.escapeSelector(target.substring(1)); // Previously, `target = target.replace(/:/g, '\\:');` @@ -42,8 +42,8 @@ }, 600, function () { $('body').removeClass('scrolling'); }); - }else{ - console.debug('Cannot scroll to target `#'+target+'`. ID not found!'); + } else { + console.debug('Cannot scroll to target `#' + target + '`. ID not found!'); } } @@ -61,7 +61,7 @@ function removeQueryParamsFromUrl() { if (window.history.replaceState) { let urlWithoutSearchParams = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.hash; - window.history.replaceState({path:urlWithoutSearchParams}, '', urlWithoutSearchParams); + window.history.replaceState({path: urlWithoutSearchParams}, '', urlWithoutSearchParams); } } @@ -72,12 +72,12 @@ * Add smooth scrolling to all links inside the main navbar. * --------------------------------------------------------------------------- */ - $('#navbar-main li.nav-item a.nav-link').on('click', function(event) { + $('#navbar-main li.nav-item a.nav-link').on('click', function (event) { // Store requested URL hash. let hash = this.hash; // If we are on a widget page and the navbar link is to a section on the same page. - if ( this.pathname === window.location.pathname && hash && $(hash).length && ($(".js-widget-page").length > 0)) { + if (this.pathname === window.location.pathname && hash && $(hash).length && ($(".js-widget-page").length > 0)) { // Prevent default click behavior. event.preventDefault(); @@ -100,7 +100,7 @@ * Hide mobile collapsable menu on clicking a link. * --------------------------------------------------------------------------- */ - $(document).on('click', '.navbar-collapse.show', function(e) { + $(document).on('click', '.navbar-collapse.show', function (e) { //get the element that was clicked, even if the element that is inside the element is e.target let targetElement = $(e.target).is('a') ? $(e.target) : $(e.target).parent(); @@ -133,55 +133,57 @@ // Use Bootstrap compatible grid layout. columnWidth: '.grid-sizer' }, - filter: function() { + filter: function () { let $this = $(this); - let searchResults = searchRegex ? $this.text().match( searchRegex ) : true; - let filterResults = filterValues ? $this.is( filterValues ) : true; + let searchResults = searchRegex ? $this.text().match(searchRegex) : true; + let filterResults = filterValues ? $this.is(filterValues) : true; return searchResults && filterResults; } }); // Filter by search term. - let $quickSearch = $('.filter-search').keyup( debounce( function() { - searchRegex = new RegExp( $quickSearch.val(), 'gi' ); + let $quickSearch = $('.filter-search').keyup(debounce(function () { + searchRegex = new RegExp($quickSearch.val(), 'gi'); $grid_pubs.isotope(); - }) ); + })); // Debounce input to prevent spamming filter requests. - function debounce( fn, threshold ) { + function debounce(fn, threshold) { let timeout; threshold = threshold || 100; return function debounced() { - clearTimeout( timeout ); + clearTimeout(timeout); let args = arguments; let _this = this; + function delayed() { - fn.apply( _this, args ); + fn.apply(_this, args); } - timeout = setTimeout( delayed, threshold ); + + timeout = setTimeout(delayed, threshold); }; } // Flatten object by concatenating values. - function concatValues( obj ) { + function concatValues(obj) { let value = ''; - for ( let prop in obj ) { - value += obj[ prop ]; + for (let prop in obj) { + value += obj[prop]; } return value; } - $('.pub-filters').on( 'change', function() { + $('.pub-filters').on('change', function () { let $this = $(this); // Get group key. let filterGroup = $this[0].getAttribute('data-filter-group'); // Set filter for group. - pubFilters[ filterGroup ] = this.value; + pubFilters[filterGroup] = this.value; // Combine filters. - filterValues = concatValues( pubFilters ); + filterValues = concatValues(pubFilters); // Activate filters. $grid_pubs.isotope(); @@ -200,7 +202,7 @@ // Filter publications according to hash in URL. function filter_publications() { - let urlHash = window.location.hash.replace('#',''); + let urlHash = window.location.hash.replace('#', ''); let filterValue = '*'; // Check if hash is numeric. @@ -210,8 +212,8 @@ // Set filter. let filterGroup = 'pubtype'; - pubFilters[ filterGroup ] = filterValue; - filterValues = concatValues( pubFilters ); + pubFilters[filterGroup] = filterValue; + filterValues = concatValues(pubFilters); // Activate filters. $grid_pubs.isotope(); @@ -224,7 +226,7 @@ * Google Maps or OpenStreetMap via Leaflet. * --------------------------------------------------------------------------- */ - function initMap () { + function initMap() { if ($('#map').length) { let map_provider = $('#map-provider').val(); let lat = $('#map-lat').val(); @@ -233,7 +235,7 @@ let address = $('#map-dir').val(); let api_key = $('#map-api-key').val(); - if ( map_provider == 1 ) { + if (map_provider == 1) { let map = new GMaps({ div: '#map', lat: lat, @@ -256,29 +258,29 @@ lat: lat, lng: lng, click: function (e) { - let url = 'https://www.google.com/maps/place/' + encodeURIComponent(address) + '/@' + lat + ',' + lng +'/'; + let url = 'https://www.google.com/maps/place/' + encodeURIComponent(address) + '/@' + lat + ',' + lng + '/'; window.open(url, '_blank') }, title: address }) } else { - let map = new L.map('map').setView([lat, lng], zoom); - if ( map_provider == 3 && api_key.length ) { - L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', { - attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', - maxZoom: 18, - id: 'mapbox.streets', - accessToken: api_key - }).addTo(map); - } else { - L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - maxZoom: 19, - attribution: '© OpenStreetMap' - }).addTo(map); - } - let marker = L.marker([lat, lng]).addTo(map); - let url = lat + ',' + lng +'#map='+ zoom +'/'+ lat +'/'+ lng +'&layers=N'; - marker.bindPopup(address + '

Routing via OpenStreetMap

'); + let map = new L.map('map').setView([lat, lng], zoom); + if (map_provider == 3 && api_key.length) { + L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', { + attribution: 'Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Mapbox', + maxZoom: 18, + id: 'mapbox.streets', + accessToken: api_key + }).addTo(map); + } else { + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + maxZoom: 19, + attribution: '© OpenStreetMap' + }).addTo(map); + } + let marker = L.marker([lat, lng]).addTo(map); + let url = lat + ',' + lng + '#map=' + zoom + '/' + lat + '/' + lng + '&layers=N'; + marker.bindPopup(address + '

Routing via OpenStreetMap

'); } } } @@ -290,10 +292,10 @@ function printLatestRelease(selector, repo) { $.getJSON('https://api.github.com/repos/' + repo + '/tags').done(function (json) { let release = json[0]; - $(selector).append(' '+release.name); - }).fail(function( jqxhr, textStatus, error ) { + $(selector).append(' ' + release.name); + }).fail(function (jqxhr, textStatus, error) { let err = textStatus + ", " + error; - console.log( "Request Failed: " + err ); + console.log("Request Failed: " + err); }); } @@ -314,7 +316,7 @@ $('#fancybox-style-noscroll').remove(); } else { // Prevent fixed positioned elements (e.g. navbar) moving due to scrollbars. - if ( !$('#fancybox-style-noscroll').length && document.body.scrollHeight > window.innerHeight ) { + if (!$('#fancybox-style-noscroll').length && document.body.scrollHeight > window.innerHeight) { $('head').append( '