How to make Jquery Darkmode load directly on the beginning? - javascript
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>
Related
I'm trying to understand why a piece of CSS/JS (for site css editing) works in two different ways depending on what I comment out
Following the method shown in this tutorial, I was able to successfully edit the css of "google.com" and the pages from its' searches. I managed to create a toggle function that somewhat works through some assistance on here, but the toggle only works when the google matching line is omitted and then applies the css changes to the extension popup and not the actual site. The code for the site-level changes still works but only when the all toggle code is omitted. I've tried rearranging the functions to see if maybe the scripting was out of order but nothing made any noticeable difference. Then tried nesting the main function that creates the css effect into the toggle itself (sits outside the toggle and then called in by a different function name), but both would still apply only to the popup. I did notice that once the toggle was on and the popup exited, upon returning to the popup, the toggle would be unchecked again. I added in options storage to see if that would solve the trick but still does not save css changes, just allowed it to save the state of the toggle. Also if the toggle is saved as checked, the css changes do not appear when opening the popup until turning it off and then back on. Below is the current code within the extension JS: //Get the URL const site = window.location.hostname //Function to add custom CSS let customStyle; const Add_Custom_Style = (css) => { customStyle = document.createElement("style") document.head.appendChild(customStyle).innerHTML = css; } const Remove_Custom_Style = () => customStyle.remove(); //Function to change CSS function changeCSS(){ //Function for Google.com if (site.includes("google.com")){/*Commenting this line out allows the toggle to take effect. To have the site-level effect take place, leave this line as is and comment out the "function changeCSS()" line above it and all code below the css string brackets.*/ Add_Custom_Style(` #import url('https://fonts.googleapis.com/css2?family=Advent+Pro:wght#300&display=swap'); * { font-family: 'Advent Pro', sans-serif !important; color: #fff !important; } a { color: #b0dff4 !important; font-size: 140%; } h1, h2, h3, h4, h5, h6 { color: #b0dff4 !important; } `) } } //***Toggle function on off window.onload = function() { document.getElementById("togBtn").addEventListener("change", function() { if(document.getElementById("togBtn").checked){ changeCSS(site); } else{ customStyle.remove(); } }); }; // Saves options to chrome.storage function saveOptions() { var cssOn = document.getElementById("togBtn").checked; chrome.storage.sync.set({ cssOn: cssOn }, function() { // Update status to let user know options were saved. var status = document.getElementById('status'); status.textContent = 'Options saved.'; setTimeout(function() { status.textContent = ''; }, 750); }); } // Restores select box and checkbox state using the preferences // stored in chrome.storage. function restoreOptions() { // Use default value chrome.storage.sync.get({ cssOn: true }, function(items) { document.getElementById("togBtn").checked = items.cssOn; }); } document.addEventListener('DOMContentLoaded', restoreOptions); document.getElementById('save').addEventListener('click', saveOptions); The main error of concern is a null parameters on the toggle function (marked by ***) I did try to see how the extension api "insertcss" would be able to apply to this but it was a bit beyond me at the moment.
Toggle switch with JS
I'm trying to learn some JS, and would like to know if anyone could help me, please. I would like to do, in a dashboard admin, an control with toggle switch to show on the index of the site whether the service is online or offline. When on, put a "online" text in a green tag. And when not working, "offline" with a red tag. How can I do this? With event listener? Thanks! Example
Here's a simple exaple to show you an approach. document.getElementById(`status`).addEventListener(`click`, function(){ const classes = this.classList; if (classes.contains(`offline`)) { this.textContent = `Online`; classes.remove(`offline`); classes.add(`online`); } else if (classes.contains(`online`)) { this.textContent = `Offline`; classes.remove(`online`); classes.add(`offline`); } }); #status { color: white; } .online { background: green; } .offline { background: red; } <span id='status' class='offline'>Offline</span>
Reveal DIV based on URL, rehide based on anchor change
I'm currently showing and hiding a DIV based on the URL, by setting the body class name: if(location.href.match("#!/~/product/category")){document.body.className+="show";} And the DIV changes accordingly: #showcase { display: none; } body.show #showcase { display: block; } Works great. Up until the AJAX cart changes the URL to #!/~/cart I would like to make the DIV disappear everywhere EXCEPT the product/category URL, but I'm stuck.
This should be done with an if-else as #HamzaKubba said. If you'd still like to apply the relevant styles with your css you can do this: // just because I have no idea what your body class usually is // you might just hard-code something else you want var defaultBodyClass = document.body.className if (location.href.match('#!/~/product/category')){ document.body.className = defaultBodyClass + ' show'; } else { document.body.className = defaultBodyClass; }
Apply CSS Repeatedly to Specific Words
I'm trying to apply CSS repeatedly and automatically to specific words. For example, for the word "Twitter" I want the colour of the text to be #00ACED. At present I am manually applying these colours around specific brand terms using span classes: <span class="twitter">Twitter</span> With the CSS: .twitter { color: #00ACED; } However, this is a process and I would prefer a method which completes this styling automatically. I have about 20 brand words with an associated colour styling. Can anyone assist me with this problem. I am using WordPress if that makes any difference.
I think the most straight-forward way to do it is by using a smart jQuery highlight plugin I came across. After applying it, you'll be able to do what you're after. Below is an example, with a link to a live fiddle at the end: HTML <p>Some examples of how to highlight words with the jQuery Highlight plugin. First an example to demonstrate the default behavior and then others to demonstrate how to highlight the words Facebook and Twitter with their own class names. Words will be highlighted anywhere in the DOM, one needs only to be specific on where the script should look for the words. It supports case-sensitivity and other options, like in the case of YouTube.</p> CSS p { line-height: 30px; } span { padding: 4px; } .highlight { background-color: yellow; } .facebook { background-color: #3c528f; color: white; } .twitter { background-color: #1e9ae9; color: white; } .youtube { background-color: #be0017; color: white; } Highlight Plugin (needs to be loaded after jQuery and before the JavaScript below) <script type="text/javascript" src="http://github.com/bartaz/sandbox.js/raw/master/jquery.highlight.js"></script> JS // default $("body p").highlight("default"); // specify class name (not case sensitive) $("body p").highlight("twitter", { className: 'twitter' }); $("body p").highlight("facebook", { className: 'facebook' }); // specify class name (case sensitive) $("body p").highlight("YouTube", { className: 'youtube', caseSensitive: true }); Include this JavaScript at the bottom of the page (before the body closing tag so that you don't need to use the function below: $(document).ready(function() { // unnecessary if you load all your scripts at the bottom of your page }); Fiddle for the win! :)
Something like this may work. You would have to loop through your search terms and this might not be the most effective way to do it. function add_class (search, replacement) { var all = document.getElementsByTagName("*"); for (var i=0, max=all.length; i < max; i++) { var text = all[i].textContent || all[i].innerText; if (text.indexOf(search) !== -1 && ! all[i].hasChildNodes()) { all[i].className = all[i].className + " " + replacement; } } } var replacements = [ ["Twitter","twitter"], // ] for (var i = replacements.length - 1; i >= 0; i--) { add_class(replacements[i][0],replacements[i][1]); }; Note: I didn't test this at all.
If you know minimum among of JavaScript, this JavaScript library can make your life much easier. it will convert all the letter in the string into a span tag. http://daverupert.com/2010/09/lettering-js/
For those of you interested in the answer, I've created a solution using WordPress functionality: function replace_custom_word($text){ $replace = array( 'Twitter' => '<span class="twitter"><a title="Twitter" target="_blank" href="http://www.twitter.com/">Twitter</a></span>', 'Facebook' => '<span class="facebook"><a title="Facebook" target="_blank" href="http://www.facebook.com/">Facebook</a></span>' ); $text = str_replace(array_keys($replace), $replace, $text); return $text;}
How can I tell if a page is in print view?
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.