Advanced Nightmode for NodeBB
-
So, turns out users /really/ like nightmode.
So while for some sites, the previous, much simpler nightmode will work fine, some will find their users demanding more complex functionality out of the nightmode as the site grows, or at least I did.
This is a far more complex setup, however- so if you find it intimidating, the simple night mode will work almost as well, with a third of the work.
So here's a more complex nightmode, with the following functionalities:
- Saved state- It will remember a users preference, and flip the nightmode to it on load.
- Auto nightmode option- Like google maps, it flips nightmode on when its night, and off when it's day.
- Instead of a cluttered toggle, separated functions
Step 1: CSS
Grab notepad or nodepad++, and your favorite web browser for development. Open up the inspector (ctrl-shift-i on chrome), and carefully tweak your way to a working night mode, copy pasting each CSS rule you make to the txt document, removing any unrelated rules (Keep only things you change!).
Be detailed! Remember dismiss dialogs, search pages, group pages, user settings pages, composers, everything.
Once you have a full night mode CSS, save this file as nightmode.css
Step 2: Putting the CSS file on your server
Use filezilla or similar to throw nightmode.css into nodebb/public
Step 3: JS
Paste the following into your header:
<script> function nightmodeon(){ var el = document.getElementById('myStyles'); if ( el !== null ) { } else { var oLink = document.createElement("link") oLink.id = 'myStyles'; oLink.href = "/nightmode.css"; oLink.rel = "stylesheet"; oLink.type = "text/css"; document.body.appendChild(oLink); } } function daymode(){ var el = document.getElementById('myStyles'); if ( el !== null ) { el.parentNode.removeChild(el); } else { var oLink = document.createElement("link") oLink.id = 'myStyles'; oLink.href = "/nightmode.css"; oLink.rel = "stylesheet"; oLink.type = "text/css"; } } function autonightmode(){ var d = new Date(); var n = d.getHours(); if (n >= 21 || n <= 5) { nightmodeon() } else{ daymode() } } function nmSwitch(){ if (Number(localStorage.nmState) == 1) { localStorage.nmState = Number(localStorage.nmState)+1; modeSet() } else if (Number(localStorage.nmState) == 2) { localStorage.nmState = Number(localStorage.nmState)+1; modeSet() } else if (Number(localStorage.nmState) == 3) { localStorage.nmState = Number(localStorage.nmState)+1; modeSet() } else { localStorage.nmState = 1; } } function modeSet(){ if (Number(localStorage.nmState) == 1) { autonightmode(); console.log('modeAuto'); } else if (Number(localStorage.nmState) == 2) { daymode(); console.log('modeDay'); $(".nightmodeCSS").html(" "); } else if (Number(localStorage.nmState) == 3) { nightmodeon(); console.log('modeNight'); $(".nightmodeCSS").html(" "); } else { autonightmode(); localStorage.nmState = 1; console.log('modeElseAuto'); } } </script>`
You also need to create a HTML footer widget, and place this inside the widget. If you do not do this, it will not work.
<script> modeSet(); </script>
Step 4: Button
The button for this CAN be simple, but that will be absolutely baffling for the user, because it has three states, one less obvious then the others. You /will/ want to style this button to have three states, one for each mode, so the user can tell what mode they're in. However, if you just want to get it working and let the users sort it out, you can simply place this:
<button class="nightmodebutton" onclick="nmSwitch();"><span></span></button>
HOWEVER, there is a special place in hell for people who do that. Ideally, you should style the above button as "OFF" in your default CSS, style it as "ON" in your nightmode CSS, then add something like:
$(".[CLASS OF SOME EMPTY DIV HERE]").html("<style>.[BUTTONCLASS] span {color: #2196f3 !important;}</style>");
into "function autonightmode()", to give it an "Auto" state.
Hopefully that wasn't too complex, I'm aware it's a bit of a wall of text. Feel free to shoot me a chat if you have issues setting this up!
-
css should be compiled with your theme, uploading to public seems like a hack for me
-
Add to custom header...
<script> $(window).on('action:widgets.loaded', function() { if (!$('li.lights-out').length) { var panel = $('<li class="lights-out"><a title="" href="#" data-original-title="Dark Theme"><i class="fa fa-fw fa-lightbulb-o"></i><span class="visible-xs-inline">Dark Theme</span></a></li>'); $('ul#logged-in-menu').prepend(panel); $('ul#logged-out-menu').prepend(panel); panel.on('click', function() { enabled = !$('body').hasClass('lights-out'); $('body').toggleClass('lights-out', enabled); localStorage.setItem('user:theme', enabled ? 'lights-out' : ''); }); } }); </script> <script> $('document').ready(function() { var theme = localStorage.getItem('user:theme'); if (theme) { $('body').addClass(theme ); } }); </script>
body.lights-out { background: none repeat scroll 0 0 #262525; color: #bdbdbd; }
Rinse and repeat with css including body.lights-out before your changes, add to custom css.
-
@exodo Anything I do will always be a hack, rule one of things I produce. I do spagetti code like some sort of horrible, programming emnem.
That is a good midway method, if much less copy and paste ease of set up for more complex tweaks then just changing out 2 or 3 divs.
However, besides the automode, that is inarguably more elegant programmatically way to accomplish that!
-
@Arc said:
That is a good midway method, if much less copy and paste ease of set up for more complex tweaks then just changing out 2 or 3 divs.
However, besides the automode, that is inarguably more elegant programmatically way to accomplish that!
My aim was to have one theme that changed the important bits to match a dark theme. Got a bit tedious keeping up with theme changes. Will rework it for Persona just as they release a new theme.
-
@a_5mith said in Advanced Nightmode for NodeBB:
Add to custom header...
<script> $(window).on('action:widgets.loaded', function() { if (!$('li.lights-out').length) { var panel = $('<li class="lights-out"><a title="" href="#" data-original-title="Dark Theme"><i class="fa fa-fw fa-lightbulb-o"></i><span class="visible-xs-inline">Dark Theme</span></a></li>'); $('ul#logged-in-menu').prepend(panel); $('ul#logged-out-menu').prepend(panel); panel.on('click', function() { enabled = !$('body').hasClass('lights-out'); $('body').toggleClass('lights-out', enabled); localStorage.setItem('user:theme', enabled ? 'lights-out' : ''); }); } }); </script> <script> $('document').ready(function() { var theme = localStorage.getItem('user:theme'); if (theme) { $('body').addClass(theme ); } }); </script>
body.lights-out { background: none repeat scroll 0 0 #262525; color: #bdbdbd; }
Rinse and repeat with css including body.lights-out before your changes, add to custom css.
If I use the code, I see 2 lightbulbs in the navbar.
-
what's your forum URL?
It's probably this, probably both menus are shown:
$('ul#logged-in-menu').prepend(panel); $('ul#logged-out-menu').prepend(panel);
-
if you need to login you can use the following
username: AAA
password: AAAAAA
-
@psychobunny if I remove one of those lines it doesn't make a different
-
How could I alter this to switch skins? I use flatly but I'd like the darkly to enable at night automagically.