So I have set up a theme switcher on my site, which stores preference in localStorage and everything works fine. Except that my code is loaded after document.ready, and checks for condition / status of theme. I also tried removing document.ready, because obviously that would remove any finishing of loading the site, but that doesn't work, and the function starts direct on load and obviously can't change any CSS, because there isn't any. For now, I am using a preloader, which is working fine, but it would be awesome if it could work without it. I have also placed the code at the beginning of the body tag, so it should execute really early. In the following, I will show you my code and a screenshot of my console, where you can see when the code gets executed. For your knowledge, I am on Shopify, if that does anything.
Any help for making my theme / code switch faster, is very much appreciated.
My Console:
console img...
My Code (I am sorry for the formatting, I made if farly quickly in the Shopify admin, so no "Prettier" and also no "IntelliSense" :) )
// Darkmode #legoon #raffaelbaer
let ALLDARKMODE = '#over-header-info-bar-legoon, #StickyBar, .full-width--return-link,' +
'.cart__subtotal, .transcy-money, .site-footer__newsletter-input, #product-title__cart-page-legoon, .cart-table,' +
'.responsive-table__row, label, .gridforsubcategories_item-grid, .linkitem_hassubcategoriesinner, .sticky--active, .sticky--open,' +
'.icon-hamburger, .icon-close, .drawer__inner, #einloggendrawerlink, .drawer__nav-link--top-level, .einloggensvgmobile, .drawer__search,' +
'.drawer__search-input, #legooninstagrammobile, #instagramiconheadermobile, .svgdarkmode, .drawer__nav-item, .drawerforsocialicons, #footerlegoonlink,' +
'.content-block, .icon-arrow-down, .product-card__name, .product-card__info, .country-selector, .site-header__search-input, .menu-sub-custom1, .menu-sub-custom2,' +
'.labelcustomnav1, .labelcustomnav2, .labelcustomnav3, .labelcustomnav4, .menu-sub-custom3, .menu-sub-custom4, .nav-bar, h1, h2, #footer-down_copyright, h3, h4, h5,' +
'h6, body, a, input, textarea, select, .link-item>a , #instagramiconheader, .site-footer, .site-footer__copyright, .darkmodeswitch, p, .site-footer__newsletter-label>p,' +
'button, #icon-wunschliste, .page-container, .labelcustomnav1>p, .labelcustomnav2>p, .labelcustomnav3>p, .labelcustomnav4>p, .site-header, .legoonlogotop, .iconuserhead, .icon-cart,' +
'.notification--success, .notification--promo, .notification__message>span, .wg-drop.country-selector, .hr-empfy_cart-page';
$(document).ready(function() {
$('.darkmodeswitch').click(function() {
/*main toggle dark mode*/
$(ALLDARKMODE).toggleClass("dark");
/*change darkmode image on mobile drawer and desktop accordingly to current mode | theme (light or dark)*/
if ($(".darkmodeswitch").hasClass("dark")) {
document.getElementById('svgdarkmode').src = "https://cdn.shopify.com/s/files/1/0571/7137/8349/files/sun.svg?v=1650307091";
document.getElementById('svgdarkmodemobile').src = "https://cdn.shopify.com/s/files/1/0571/7137/8349/files/sun.svg?v=1650307091";
localStorage.setItem("theme", "dark");
} else {
document.getElementById('svgdarkmode').src = "https://cdn.shopify.com/s/files/1/0571/7137/8349/files/moon.svg?v=1650306791";
document.getElementById('svgdarkmodemobile').src = "https://cdn.shopify.com/s/files/1/0571/7137/8349/files/moon.svg?v=1650306791";
localStorage.setItem("theme", "light");
};
});
// Am Anfang
if (localStorage.getItem("theme") === "dark") {
console.log("Darkmode status = true");
$(ALLDARKMODE).addClass("dark");
} else {
console.log("Darkmode status = false");
$(ALLDARKMODE).removeClass("dark");
}
$('.darkmodeswitch').click();
});
For a dark mode switch, simply toggle a CSS class on the HTML element (document.documentElement.classList.toggle('dark');), and use that as a contextual selector for changes on your elements. Use CSS custom properties for the changes.
Here's an example of the approach. Please note that localStorage is unavailable in StackOverflow snippets due to security reasons, so I left that part out (you've got that working already anyway).
function toggleDarkMode() {
document.documentElement.classList.toggle('dark');
}
:root {
--body-bg-color: #fff;
--btn-bg-color: #f0f0f0;
--btn-fg-color: #333;
}
:root.dark {
--body-bg-color: #666;
--btn-bg-color: #333;
--btn-fg-color: #f0f0f0;
}
body {
background-color: var(--body-bg-color);
}
button {
background-color: var(--btn-bg-color);
border: 1px solid #888;
color: var(--btn-fg-color);
}
<button type="button" id="toggle" onclick="toggleDarkMode()">Dark Mode Button</button>
I want to change the background color of a row if the value in the table cell goes above a certain value.
I have tried implementing the toggle class as well as adding and removing classes with no luck. When I manually implemented the background color it worked.
I know I am trying to toggle a class vs a style, but is there any way I can toggle a style to change the background color?
var mq2 = 5;
if (mq2 >= 5) {
document.getElementById("row1").classlist.toggle("change2");
} else {
document.getElementById("row1").classlist.toggle("change1");
}
.change1 {
background-color: #FF6347;
}
.change2 {
background-color: #90EE90;
}
<tr id="row1">
Your code should work. You could improve it by creating a variable referencing the element
const row = document.getElementById("row1");
if(someCondition) {
row.classList.toggle("change2");
} else {
row.classList.toggle("change1");
}
The approach you are taking is fine, just make sure you capitalize classList correctly.
document.getElementById('row1').classList.toggle('change1');
According to This page I was able to remove all the CSS preloaded and added on the webpage using that. I wanted to implement a button system where "onclick" = enable/disable webpage CSS even the ones pre-loaded by my web-host. I would like to eliminate the style tags to prevent lags for my website users. I prefer using the script that I have linked above unless there is another alternative that works better. Is it possible to enable CSS onclick the same button to disable? If not is it possible, can it be done with this quick? example with the preferred script below:
if (disable) {
style = "disable";
} else {
location.reload();
}
PREFERRED SCRIPT:
function removeStyles(el) {
el.removeAttribute('style');
if(el.childNodes.length > 0) {
for(var child in el.childNodes) {
/* filter element nodes only */
if(el.childNodes[child].nodeType == 1)
removeStyles(el.childNodes[child]);
}
}
}
removeStyles(document.body);
What about a different aproach?
Add initially a class to a body called 'styled' for example
<body class="styled">
use it as a main selector in your css definitions
<style>
.styled a { ... }
.styled h1 { .... }
</style>
then an example jquery script to toggle the class:
<script>
$(function() {
$('#myswitch').click(function() {
$('body').toggleClass('styled');
});
});
</script>
when class is present, the page will be styled, when absent there will be no styling.
Of coures there could be better aproach, but this is the first thing which pops up in my mind
To remove all style on an element, you could do
function removeStyles(el) {
el.style = {};
}
If you want to enable/disable the CSS on the page, then the goal is not to merely remove all the styles on the page, but you will need to save them somewhere also so they can be recalled when the user re-clicks the button. I would recommend having jQuery to help you with this, and it could be done the following way:
var style_nodes = $('link[rel="stylesheet"], style');
style_nodes.remove();
$('*').each(function(num, obj) {
var style_string = $(obj).attr("style");
if (style_string) {
$(obj).data("style-string", style_string);
$(obj).attr("style", "");
}
});
Now you've saved the stylesheets and style DOM nodes inside of style_nodes, and the actual style attribute inside of a jQuery data attribute for that specific DOM node. When you click to add the CSS back to the page, you can do the following:
$('head').append(style_nodes);
$('*').each(function(num, obj) {
if ($(obj).data("style-string"))
$(obj).attr("style", $(obj).data("style-string"));
});
Check out this JS Fiddle I put together to demonstrate it:
https://jsfiddle.net/5krLn3w1/
Uses JQuery, but I'm sure most frameworks should give you similar functionality.
HTML:
<h1>Hello World</h1>
Turn off CSS
Turn on CSS
JS:
$(document).ready(function() {
$('a#turn_off').click(function(evt) {
evt.preventDefault();
var css = $('head').find('style[type="text/css"]').add('link[rel="stylesheet"]');
$('head').data('css', css);
css.remove();
});
$('a#turn_on').click(function(evt) {
evt.preventDefault();
var css = $('head').data('css');
console.info(css);
if (css) {
$('head').append(css);
}
});
});
CSS:
body {
color: #00F;
}
h1 {
font-size: 50px;
}
Besides a different color for each nav item when they are active i need to have my site-title (logo background color) another color for each page/album.
When a link inside the nav is active, .k-nav-current is automatically appended.
So i've tried this:
if ($("#main li:nth-child(2)").hasClass('.k-nav-current')) {
$("#site-title").addClass("babycurrent");
} else {
};
.babycurrent{
background: rgb(35,235,0);
}
Or instead of #main li:nth-child() i've tried:
#main a#unique_nav_itemid
a#unique_nav_itemid
But none of these solutions are working.
One method you can use to test to see if the element exists in the document:
if($('.k-nav-current').length) {
$("#site-title").addClass("babycurrent");
}
of course if length is 0, it is considered "falsey". any other positive number is "truthy".
However, for any further help, we will need to see the actual markup.
EDIT:
For your current setup, you are trying to use #main li:nth-child(2) and checking its class. The class is actually applied to the anchor. You need to use #main li:nth-child(2) a
if ($("#main li:nth-child(2) a").hasClass('k-nav-current')) {
$("#site-title").addClass("babycurrent");
}
Though it might be better to just use something like this (considering ids are unique):
if ($("#baby").hasClass('k-nav-current')) {
$("#site-title").addClass("babycurrent");
}
Lastly, if you really want it dynamic, you can do something like this:
var current = $("a.k-nav-current")[0].id.replace('#','');
$("#site-title").addClass(current + "current");
EDIT:
$( document ).ready(function() {
if ($("#baby").hasClass('k-nav-current')) {
$("#site-title").addClass("babycurrent");
}
});
// or you can do this (commented out) /*
$( document ).ready(function() {
var current = $("a.k-nav-current")[0].id.replace('#','');
$("#site-title").addClass(current + "current");
});
*/
I'm using a simple toggle of the CSS display attribute from none to block in a FAQ page. However, I want the page to show everything when printing. What happens now is if you go to the page and go to print mode, it'll open all the closed items since I added this code to my print.css stylesheet...
.faq
{
display:block;
}
However, if you open an item, close it again, and then go to print mode, that item will remain closed.
My JS code looks like this...
` var divNum = new Array("faq1", "faq2", "faq3", "faq4", "faq5", "faq6", "faq7", "faq8", "faq9", "faq10", "faq11", "faq12", "faq13");
function openClose(theID) {
for (var i = 0; i < divNum.length; i++) {
if (divNum[i] == theID) {
if (document.getElementById(divNum[i]).style.display == "block") { document.getElementById(divNum[i]).style.display = "none" }
else { document.getElementById(divNum[i]).style.display = "block" }
}
}
}`
and the HTML looks like this
<a class="faq" onClick="openClose('faq1')">Question?</a><br />
<p id="faq1" class="faq">Answer</p>
What can I do to make sure everything is opened when I go into print mode?
Instead of manipulating the display status of an element directly with your JS code, I would have classes defined in CSS then simply toggle the classes using JS.
If your classes are defined for #media screen only then you won't have to worry about what the current display status is of any of the FAQ entries.
EDIT: For example, in your CSS file:
#media screen .faq.open {
display: block;
}
#media screen .faq {
display: none;
}
Then your JS would look like:
function openClose(theID) {
for (var i = 0; i < divNum.length; i++) {
if (divNum[i] == theID) {
if (document.getElementById(divNum[i]).className.match(new RegExp('(\\s|^)open(\\s|$)'))) { document.getElementById(divNum[i]).className = ele.className.replace(new RegExp('(\\s|^)open(\\s|$)'), ' '); }
else { document.getElementById(divNum[i]).className += " open" }
}
}
}
Note, I haven't tested this so there may be some syntax errors. Also, most of my projects already include jQuery so the method I typically use is much cleaner code. I have not used jQuery here because you didn't use it in your code samples.