I have made a dark mode button with my own dark theme. The theme is saved by Local Storage. Also when I click the button, then it's icon change (moon to sun). But if I reload the page, the site is still in dark mode but the button icon's is the moon again. So heres a link which show you the problem if youo don't understant what i am talking about. (https://postimg.cc/yg6Q3vq0)
Also heres my code:
//This is the darkmode script.
function darkmode() {
const wasDarkmode = localStorage.getItem('darkmode') === 'true';
localStorage.setItem('darkmode', !wasDarkmode);
const element = document.body;
element.classList.toggle('dark-mode', !wasDarkmode);
}
function onload() {
document.body.classList.toggle('dark-mode', localStorage.getItem('darkmode') === 'true');
}
//End
//And this is the code which change the button's icon
$('button').on('click', fav);
function fav(e) {
$(this).find('.fa').toggleClass('fa-moon-o fa-sun-o');
}
//So I would like to combine the 2 codes. I mean to add the icon code to Local Storage.
.card {
color: yellow;
background-color: blue;
}
.dark-mode .car {
color: blue;
background-color: yellow;
}
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<a style="padding: 0 !important;"><button class="darkmode" onclick="darkmode()"><i class="fa fa-moon-o"></i></button></a>
<div class="card">
<h1>Title</h1>
<p>Text<//p>
<h2>Another text..</h2>
</div>
</body>
</html>
The browser just renders the HTML as written. Your HTML says to render <i class="fa fa-moon-o"></i>, so that's what the browser shows. In other words, it will always show the moon icon by default.
You need to perform some kind of check on page load to see if the icon should be changed.
Something like this might work:
// when the document is ready
$(document).ready(function () {
// check if dark mode is enabled
if (localStorage.getItem('darkmode') === 'true') {
// if it is, change the moon icon to a sun icon
('.fa').toggleClass('fa-moon-o fa-sun-o');
}
});
Related
(I will link a code sandbox with all my code (at its latest) to be viewed if you want to)
https://codesandbox.io/s/distracted-hellman-pyej06?file=/index.html
I have two issues that I was hoping to address
Problem-1: I have a website called dirieahmed. ml (the same as the code sandbox) I have a night mode / light mode toggle, however when I click on night mode my logo (the image which is called hello.jpg and is above the face picture) will stay the same which makes sense but looks terrible because it looks like an imperfect white square. As a result, I wanted to change this. Therefore when I click on night mode I want the image to change into the night mode version of the logo I have made (it will be called hello-dark.jpg) Is there a way i can do that? I will link the appropriate code down below but if you would like to see the CSS you can view the sandbox
<div class="image1">
<img src="img/hello.jpg" alt="something" width="400" height="300">
</div>
<script async>
<--!This is my dark theme toggle-->
document.querySelector('.theme-toggle-button').addEventListener('click', () => {
document.body.classList.toggle('dark')
})
Problem-2: On my sandbox, you can view an About me, Education and Achievements and Other content elements, these elements are buttons when clicked they will drop down a content, if I click on about me then Education about me will open then close and allow Education to open. Pretty Normal and similarly for the button called "Other" but when i click on Other again to reset all the views and make it clean like when it was originally where no dropdowns exsisted that wont happen. Is there a way for me to make a javascript that will close all content from that div when clicked on it twice. (the code of CSS is in the sandbox but Html and JS will be here)
<div class="container">
<button id="one" class="click one" title="click me">About Me</button>
<div class="list-1 sec">
<h1 class="content-header-one content">Dummy text header</h1>
<p class="content-paragraph-one">Dummy text</p>
</div>
<button class="click two" title="click me">Education and Achivements</button>
<div class="list-2 sec">
<p class="content-paragraph2 content">Dummy text</p>
<ul class="content-list content">
<li>- Achivement #1</li>
<li>- Achivement #2</li>
<li>- Achivement #3</li>
</ul>
</div>
<button class="click three" title="click me" >Other</button>
<div class="list-3 sec">
<h1 class="content-header-two content">Dummy text header</h1>
<p class="content-paragraph3 content">Dummy text</p>
</div>
<script async>
// Instanciate List div's
let list1 = document.querySelector(".list-1");
let list2 = document.querySelector(".list-2");
let list3 = document.querySelector(".list-3");
// Reset's all views to the default without .newlist
const resetAllViews = () => {
list1.classList.remove("newlist");
list2.classList.remove("newlist");
list3.classList.remove("newlist");
};
// Checks to see what button is clicked and shows correct list based on input
document.addEventListener(
"click",
function (e) {
e = e || window.event;
var target = e.target;
if (target.classList.contains("one")) {
resetAllViews();
list1.classList.add("newlist");
}
if (target.classList.contains("two")) {
resetAllViews();
list2.classList.add("newlist");
}
if (target.classList.contains("three")) {
resetAllViews();
list3.classList.add("newlist");
}
}, false);
</script>
</div>
Again you can view the result I have in the sandbox (latest) and on the most recent website dirieahmed.ml for real life view
Sorry if I repeated myself a lot and any help would be appreciated though I prefer if you can show me the code as a runner snippet as I am fairly new so its a bit difficult for me to understand all vocabulary but again any help is appreciated
As for the 1st point, i think you have 2 possibilities:
Add the image as a background image with css, so you can easily toggle. Normally you show the "light" image, and if the body has the dark class then you can show the "dark" image.
The second idea is to add two <img> elements to the page and hide / show accordingly, something like:
.image-light {
display: block;
}
body.dark .image-light {
display: none;
}
.image-dark {
display: none;
}
body.dark .image-dark {
display: block;
}
As to the 2nd point i think you should to it like this:
you have a variable to hold the current open element
when you click a button you get the "value" vor that button
If the value if the same as the current open variable, then you reset the variable (maybe to null), otherwise you set the current open variable to the value of that button
Then you can have an update function. On this function you go through all the of "target" elements. If the element corresponds to the currently open variable, you open it, otherwise you close it.
Something like:
let currentlyOpen = null;
let buttons = document.querySelectorAll(".your-buttons");
let targets = document.querySelectorAll('.your-targets');
button.forEach((button) => {
button.addEventListener('click', (event) => {
const newTarget = event.target.getAttribute('your-identifier-attribute');
currentlyOpen = currentlyOpen === newTarget ? null : newTarget;
updateUI();
});
})
function updateUI() {
targets.forEach((target) => {
targetIdentifier = target.getAttribute('the-identifier-attribute');
targetIdentifier === currentlyOpen
? target.classList.add('your-class-for-open-list')
: target.classList.remove('your-class-for-open-list');
})
}
I have created an example for you:
let openContent = null;
const buttons = document.querySelectorAll('button');
const contents = document.querySelectorAll('.content');
buttons.forEach((button) => {
button.addEventListener('click', (event) => {
const newTargetId = event.target.getAttribute('target-id');
openContent = newTargetId === openContent ? null : newTargetId;
updateUI();
});
});
function updateUI() {
contents.forEach((content) => {
const contentId = content.getAttribute('id');
contentId === openContent
? content.classList.add('visible')
: content.classList.remove('visible');
});
}
.content {
display: none;
}
.content.visible {
display: block;
}
<p> click one of the buttons to show more content</p>
<button target-id="one">One</button>
<button target-id="two">Two</button>
<button target-id="three">three</button>
<p class="content" id="one">Content one</p>
<p class="content" id="two">Content two</p>
<p class="content" id="three">Content three</p>
Here is an example of doing this using two elements where one is hidden based on theme. You could make it a photo that you want to change. This way both images are loaded and you don't have to have the client wait for an image to load when themes change.
The way I accomplished this was mainly in css. The only javascript is to toggle the dark class on the page. The dark page has css variables which represent whether or not elements on the page have a display of none or block. On the actual elements which toggle, I feed those css variables into them. It is also possible to add animations or transitions to make it feel fancy, but hopefully this small demonstration satisfies your need for modifications to your own project.
const $ = str => document.querySelector(str);
const page = $(".page");
$(".theme-toggle").addEventListener("click", () => {
page.classList.toggle("dark");
});
body {
display: grid;
place-items: center;
}
.page {
--light-logo: block;
--dark-logo: none;
display: flex;
flex-direction: column;
text-align: center;
}
.page.dark {
--light-logo: none;
--dark-logo: block;
background-color: black;
color: white;
}
.logo-container {
font-size: 5rem;
}
.logo-container .dark {
display: var(--dark-logo);
}
.logo-container .light {
display: var(--light-logo);
}
<div class="page">
Hello World
<div class="logo-container">
<div class="light">π</div>
<div class="dark">π</div>
</div>
<button class="theme-toggle">π / π</button>
</div>
Answer 1: It is possible to simple solve by CSS, but this is not good idea for the SEO optimization. Better and most simple solution is to use 2 images and add class "hidden", where you will set for this class {display:none} in css file. Next you must modify your script to set/remove "hidden" class by the selected light/dark mode.
<div class="image1">
<img src="img/hello.jpg" alt="something" width="400" height="300">
</div>
Another better solution is modify the DOM, replace img element when mode is changed, or change the src attribute, e.g.:
document.getElementById("myImageId").src="img/hello-dark.jpg";
I have a simple HTML Code in combination with css and JavaScript.
When you are clicking on a link, your URL will be updated like "#link1". Then the visibility of an overlay turn on visible, which is only shown at "#link1"
Now the problem:
When I click on the link my screen automatically scrolls to this overlay, but I didn't want that.
I tried "return false" or "event.preventDefault()". This works, but my URL didn't get updated, so my overlay will not appear.
Dose anyone has an idea how I can do this?
Also tried:
return null
event.preventDefault()
onClick
----html----
<!--The Link-->
<area href="#link1" shape="rect" coords="0,0,100,100" />
<!--The Overlay-->
<div id="link1" class="overlay">
<div class="popup">
...some text...
</div>
</div>
----css----
.overlay {
visibility: hidden;
... some other stuff ...
}
.overlay:target {
visibility: visible;
}
Can you do it this way instead of using href="#link1", do href="javascript:void(0)", and make overlay property appear using jquery property link
$('body').on('click','a', function(){
//Something here
}
Start by setting the display property of the overlay class to none
You need to create a function that will get triggered when the page is loaded or when a link that starts with # is clicked.
That function will get the hash of the url, get the corresponding element and set its display property to something other than none
This way the element won't be visible when the page loads or the hash is changed.
if (document.readyState === "complate") onLoad();
else addEventListener("load", onLoad);
function onLoad() {
var target = document.getElementById(new URL(document.URL).hash.substring(1));
if (target && target.classList.contains("overlay")) {
target.classList.add("active");
}
}
document.querySelectorAll("[href^='#']").forEach(function(link) {
link.addEventListener("click", function() {
setTimeout(onLoad, 0);
});
});
.overlay {
display: none;
}
.overlay.active {
display: block;
}
Show overlay
<!--The Overlay-->
<div id="link1" class="overlay">
<div class="popup">
...some text...
</div>
</div>
The other simpler solution is to use position: fixed to make the elements position static and always have it on the view-port (elimination the need for scrolling).
I want to change the color of the whole website when I click on a button. This will remain whenever I do not change. If I go to another page, the color should remain the same as what I previously selected.
E.g. https://india.gov.in/
In the top header, when select the color black, whole website will be black until we do not change. Same I want functionality.
I have done to change the color on current but not wholw page. When I go to another page default colors is coming.
<script>$(document).ready(function () {
$('#demo-wrapper ul li').on('click', function () { var path = $(this).data('path');$('#color-switcher').attr('href', path); });
}); </script>
<ul class="dropdown-menu multicolors-name">
<li data-path="Content/theme/assets/admin/css/custom_website.cssββ">
Green</li><li data-path="Content/theme/assets/admin/css/blue.css"><a href="#" >Blue</a>
</li>
</ul>
A way to do this, get a master.css file. Inside this file you can import your other css files. Like this:
#import 'header.css'
#import 'main.css'
Then you can have another master-theme2.css where you would import other css files. The way to change your master.css file is like this:
https://stackoverflow.com/a/22445820/4673847
For keeping the theme per page, you should use sessions or cookies
The easiest way to do this is with help of some css preprocessor for example LESS. Then you can loop over prepared color schema setting:
.generate-widget-colors(#list) {
.iter(length(#list));
.iter(#index) when (#index > 0) {
.iter(#index - 1);
#item: extract(#list, #index);
#key: extract(#item, 1);
#color: extract(#item, 2);
.color-schema-#{key} {
color: #color;
}
.background-color-schema-#{key} {
background-color: #color;
}
div.connect-container.wizard-schema-#{key} > div > div > div > h3 {
color: #25414c;
}
div.connect-container.wizard-schema-#{key} .widget-icon {
color: #Green;
}`
}
}
.generate-widget-colors(#WidgetColors);
This is my own example when I pass the color(key) value into this loop from my backend and all my widgets get new colors. And for saving the schema you can use browsers local storage for example or if you have an authentication then ofc store user schema in db
in layout apply this jquery. Get the selected color value and apply it here.
window.jQuery("#ButtonId").click(function ()
{
window.jQuery('#Layoutid').css("color", "selectedcolor");
});
You can make use of HTML5 local storage or cookies to achieve it. You need to store the selected color and then retrieve it on window load.
I have created a working fiddle based on HTML 5 local storage. Just select a color and reload the fiddle, the background color will remain the same as you selected.
You can switch CSS files with something like this.
<span class="css-selector" id="style1" data-css="path_to_style1.css">Theme 1</span>
<span class="css-selector" id="style2" data-css="path_to_style2.css">Theme 2</span>
$(".css-selector").click(function() {
$("head link#maincss").attr("href", $(this).data("css")); //where main css is placed in head like <link rel="stylesheet" id="maincss" type="text/css" href="path_to_style1.css">
}
And for simple color switching, you can use this code:
<div class="selector">
<span class="color red" data-color="#990000"></span>
<span class="color green" data-color="#009900"></span>
<span class="color blue" data-color="#000099"></span>
</div>
<div class="content">
India is a "Sovereign, Socialist, Secular, Democratic Republic" with a parliamentary system of government. This section seeks to introduce the Constitution of India, its origin, the Parliament, various Acts and Rules that govern the nation, Documents, Public Notifications, Welfare Schemes and Application Forms to avail them, apart from updates on whatβs happening around us. Know the "Who's Who" of the Indian Government and check out a range of such vital information that may help you in your daily life.
</div>
$(document).ready(function(){
var themeColor="#ffffff"; // define default theme color
if(typeof(Storage) !== "undefined") {
if (localStorage.themeColor) {
themeColor = localStorage.themeColor //get stored color
}
$('.content').css('background', themeColor); set stored color as background
}
});
$('.selector .color').click(function(){
themeColor = $(this).data("color");
$('.content').css('background', themeColor); //set selected color as background
if(typeof(Storage) !== "undefined") {
localStorage.themeColor = themeColor; // store selected color
};
});
.color{
display:inline-block;
height:20px;
width:20px;
border-radius:50%;
margin:5px;
cursor:pointer;
}
.red{
background-color:red;
}
.green{
background-color:green;
}
.blue{
background-color:blue;
}
Check it here. https://jsfiddle.net/hcfejaez/3/
I have an HTML page with two buttons: a light theme button and a dark theme button. When I click the light theme button the background will turn light gray and text is black, when I click the dark theme button the background will turn black and text is white.
When I reopen my page the last theme selected should be generated.
so here is my html:
<html>
<head>
<script type="text/javascript" src="js/index.js"></script>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/index.css">
</head>
<div class="MyPage">
<body>
<h1>choose a theme:</h1>
<input id="b1" type="button" value="light theme">
<input id="b2" type="button" value="darck theme">
<p>this a sample for using API local storage in HTML5 </p>
</body>
</div>
</html>
css:
.MyLightPage
{
background-color: gray;
text-decoration-color: black;
}
.MyDarkPage
{
background-color: black;
color: white;
}
My problem is how to connect the 3 diverse types of my project (HTML, CSS and JavaScript) and what functions should be existing in my JavaScript file to make this happen.
This can be easily done using JavaScript.
The buttons call different functions where the background and text color is being set.
#MyPage {
background-color: black;
color: white;
}
<div id="MyPage">
<h1>choose a theme:</h1>
<input id="b1" onclick="lightTheme()" type="button" value="light theme">
<input id="b2" onclick="darkTheme()" type="button" value="dark theme">
<p>this a sample for using API local storage in HTML5 </p>
<script>
function darkTheme() {
document.getElementById('MyPage').style.backgroundColor = "black";
document.getElementById('MyPage').style.color = "white";
}
function lightTheme() {
document.getElementById('MyPage').style.backgroundColor = "white";
document.getElementById('MyPage').style.color = "black";
}
</script>
</div>
This snippet shows how to set the relevant CSS classes upon the click of a button. Saving the selecting theme can be added to the JS part easily - please refer to the very simple Localstorage API for details.
$('#b1').click(function() {
$('body').attr("class","MyLightPage");
});
$('#b2').click(function() {
$('body').attr("class","MyDarkPage");
});
.MyLightPage
{
background-color: gray;
text-decoration-color: black;
}
.MyDarkPage
{
background-color: black;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="MyPage">
<h1>choose a theme:</h1>
<input id="b1" type="button" value="light theme">
<input id="b2" type="button" value="dark theme">
<p>this a sample for using API local storage in HTML5 </p>
</div>
</body>
As a side note, please also have a look at how a basic HTML document is structured. The body tag should not be the child of any divs, it has to be the direct child of the html tag.
If you want to maintain the state of the last color that is clicked you need to hold some data on the server. The DOM will refresh every time you do a hard page reload. Database data, however, maintains the data that you can fetch on every page load. You can update this database data when one of the buttons is clicked. You have different ways to implement this. An example could be:
.theme-styling{
<?php echo getDarkOrLightThemeCode(); ?>
}
Then in the DOM, you can assign theme styling to specific elements that have a light and dark element styling:
<button class="btn btn-large theme-styling">Hello</button>
<button class="btn btn-large theme-styling">Goodbye</button>
You can add an id to specific elements if you want additional styling apart from your dark and light theme styles.
And then specifically, when the user clicks a dark theme button or light theme button, you should create an AJAX request to update the variable property on the server.
try this:
var element = document.querySelector('body'),
button = document.querySelector('#myButton');
button.addEventListener('click',function(){
if(element.className == 'MyLightPage'){
element.className = 'MyDarkPage';
}else{
element.className = 'MyLightPage';
}
});
I have a Q&A list with "Open All/Close All" at the top with individual open and close image buttons that toggle when clicked. That works fine.
Then follow individual Q&As, and each has its own open and close image.
If you click on "Open All/Close All" first, as soon as the page loads, and then click on the individual Q&A open/close images, all works fine. But if after page load you click on the individual Q&A open/close images, bypassing "Open All/Close All," they display the inappropriate open or close image.
Here is page code:
<div class="answersee"><span>Open All</span><img src="assets/open.gif" border="0" alt="" /></div>
<div class="answerhide"><span>Close All</span><img src="assets/close.gif" border="0" alt="" /></div>
<div class="qa">
<div><img src="open.gif" border="0" alt="" /><span class="question">Question.</span></div>
<div class="answer"><p>Answer.</p></div>
</div>
Here's the script (also uses Jquery):
$(function () {
$(".qa").click(function () {
$(this).find("div").next().slideToggle("fast");
if ($(this).find("div:eq(0)").find("img").attr("src") == "open.gif") {
$(this).find("div:eq(0)").find("img").attr("src", "close.gif");
}
else {
$(this).find("div:eq(0)").find("img").attr("src", "open.gif");
}
});
$(".answersee").click(function () {
$(".answer").show("fast");
$(".qa > div > img").attr("src", "close.gif");
$(".answerhide").show();
$(".answersee").hide();
})
$(".answerhide").click(function () {
$(".answer").hide("fast");
$(".qa > div > img").attr("src", "open.gif");
$(".answersee").show();
$(".answerhide").hide();
})
});
I don't think it's a CSS problem, or I'd include that code here. Do I need to initialize the script in some way? Or did I make a mistake in the above script?
Here's how I would do it.
Working Demo β
EDIT:
Update the code to have simple open/close link.
Code with comments which explains my approach:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<style>
body
{
font-family: "Verdana";
font-size: 12px;
}
.question
{
background-color: #ccc;
cursor: pointer;
padding: 5px;
margin-bottom: 10px;
border-bottom: 1px solid #000;
}
.answer {
padding: 5px;
}
</style>
<script>
$(document).ready(
function()
{
//Hide all the answers on page load.
$('.answer').hide();
//For all questions, add 'open'/'close' text.
//You can replace it with an image if you like.
//This way, you don't need to specify img tag in your HTML for each question.
$('.question')
.append(' <span>[ open ]</span>');
//Now there are two ways to toggle the visibility of answer.
//Either click on the question OR click on Open All / Close All link.
//To use the same code for both instances, we will create
//a function which will take the 'question' div and toggle the answer for it.
//Advantage of this approach is that the code to toggle the answer is in
//one place.
//By default, this function will try to toggle the status of the answer
//i.e. if it's visible, hide it otherwise show it.
//This function will take a second argument called 'showAnswer'.
//If this argument is passed, it overrides the toggle behavior.
//If 'showAnswer' is true, answer is shown.
//If it's false, answer is hidden.
//This second parameter will be used by the 'openAll', 'closeAll' links.
var toggleAnswer = function toggleAnswer(question, showAnswer)
{
//The way I have structured the HTML, answer DIV is right after
//question DIV.
var $answer = $(question).next('div');
//Animation callback, after the animation is done, we want to
//switch the 'text' to display what could the user do with the question.
//Once again, you can change this code to show open/close image.
var updateText = function()
{
var text = $answer.is(':visible') ? ' [close] ' : ' [open] ';
$(question).find('span').html(text);
}
var method = null;
if(arguments.length > 1)
{
//If the function was called with two arguments, use the second
//argument to decide whether to show or hide.
method = showAnswer === true ? 'show' : 'hide';
}
else
{
//Second argument was not passed, simply toggle the answer.
method = $answer.is(':visible') ? 'hide' : 'show';
}
$answer[method]('fast', updateText);
};
//On each question click, toggle the answer.
//If you have noticed, I didn't enclose both Q&A inside one DIV.
//The way you have done if user clicks on the answer, answer will collapse.
//This may not be desirable as user may want to copy the answer
//and he won't be able to.
$('.question').click(function(){ toggleAnswer(this);});
//We will reuse the same toggleAnswer method in openAll, closeAll
//handling. This way, if you want to change behavior of how the question/answers
//are toggled, you can do it in one place.
$('#openClose').click(
function()
{
var showAnswer = $(this).html().toLowerCase().indexOf('open') != -1 ? true : false;
$('.question').each(function() { toggleAnswer(this, showAnswer); });
$(this).html(showAnswer ? 'Close All' : 'Open All');
return false;
}
);
}
);
</script>
<html>
<head>
<title>simple document</title>
</head>
<body>
<a id='openClose' href='#'>Open All</a>
<br /><br />
<div class='question'>Question 1</div>
<div class='answer'>Answer 1</div>
<div class='question'>Question 2</div>
<div class='answer'>Answer 2</div>
<div class='question'>Question 3</div>
<div class='answer'>Answer 3</div>
</body>
</html>
You need to use the callbacks because your animation will not have finished by the time to check for which image is being shown.
$(".qa").click(function() {
$(this).find("div").next().slideToggle("fast", toggleImage);
}
function toggleImage(){
var $img = $(this).find("img");
$img.attr('src') == "open.gif" ? $img.attr('src', "close.gif") : $img.attr('src', "open.gif");
}
N.B There are better ways to do this but lets get you working first and then see if you want to refactor it some more.
Thank you for taking the time to provide this. I will try this later today and report back. In my version, I toggle the Open All/Close All feature. It's a cleaner look and easier to use, since you don't have to move your mouse.
Redsquare and Solution Yogi:
Thanks. I will reply again later and also post a working demo so you can see the problem more clearly. Sorry, I should have done that before.
Liz