window.matchMedia Javascript to remember user selection on page change - javascript

I'm having trouble with prefers-color-scheme with the logic that I'm trying to achieve. For example, with the prefers-color-scheme I have a toggle on my site that overrides this is a user prefers black while using light mode, and vice versa. The issue I'm running into is I can't toggle it so that when a user changes the toggle to set it to the OS color theme, when they switch pages the theme switches back to the prefers color scheme. I already have local storage setup and variables called theme type and on.
When I comment out the detect color scheme function, the local storage remembers the users desired theme setting. When uncommented it overrides and always picks the theme os color scheme. How can I get my logic working right where when on the users first entry point before the local storage is created that it reads the theme OS but if the user changes the theme to black and vice versa that the OS doesn't override when on page change?
Thanks.
So the detectColorScheme checks users OS theme.
function detectColorScheme(){
var on = 1;
on = 1;
if (window.matchMedia('(prefers-color-scheme: dark)').matches && on <= 1) {
if (on = 1 ) {
on = 2;
darkmode();
console.log("OS Setting DARK MODE");
}
}
if (window.matchMedia("(prefers-color-scheme: light)").matches ) {
if (on = 1) {
lightmode();
console.log("OS Setting LIGHT MODE");
}
}
}
Then at the start of the javascript file I do the following :
document.body.style.backgroundColor = "";
if (localStorage.themepref == 1 ) {
detectColorScheme();
document.body.style.backgroundColor = "#FFF";
lightmode();
}
else {
detectColorScheme();
document.body.style.backgroundColor = "#0a0a0a";
darkmode();
localStorage.themepref = 2;
}
window.onload = function() {
console.log('First');
if (event.target.readyState === 'loading') {
detectColorScheme();
$('body').css({ background: ''});
document.body.style.backgroundColor = "inherit";
if(lightmodeON == true) {
detectColorScheme();
$('body').css({background: "#fbfcfd"});
document.body.style.backgroundColor = "#FFF";
}
if(lightmodeON == false) {
detectColorScheme();
$('body').css({background: "#0a0a0a"});
document.body.style.backgroundColor = "#0a0a0a";
}
}
};
And lastly
document.addEventListener("DOMContentLoaded", function() {
window.scrollTo(0, 0);
$(window).scrollTop( $("#top").offset().top );
$(document).scrollTop(0);
document.body.style.backgroundColor = "";
if (document.readyState === 'complete') {
if(lightmodeON == true) {
$('body').css({background: "#fbfcfd"});
console.log('loading white bg');
}
if(lightmodeON == false) {
$('body').css({background: "#0a0a0a"});
console.log('loading black bg');
}
}
if (typeof (Storage) !=="undefined") {
if (localStorage.themepref == 1 ) {
lightmode();
}
else {
darkmode();
localStorage.themepref = 2;
}
if(lightmodeON == true) {
$('body').css({background: "#fbfcfd"});
console.log('loading fffwhite bg');
}
if(lightmodeON == false) {
$('body').css({background: "#0a0a0a"});
console.log('loading black bg');
}
}

I have done this small effort, What I am doing is:
When user will load the website for first time, localStorage will be empty so we will setup the theme according to OS but then if user plays with our toggle, which if on then lightmode otherwise darkmode, then we will also save this in localstorage and next time when ever user will visit our page, we will check it's preference from the local storage, will never go back to OS theme.
Please have a look and let me know if it is any helpful. It will not work here as localStorage will not be supported here. Please copy and test in your browser.
<html lang="en">
<head>
<meta charset="utf-8">
<title>test</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<label style="color:yellow;">IsLightMode: </label>
<input id="toggleCheck" type="checkBox" onclick="toggle()" />
<script>
var lightmodeOn = true;
function changeColorOfBackground(lightmodeOn) {
if(lightmodeOn == true) {
// you can call your lightmode function here if want to set other things too.
$('body').css({background: "#fbfcfd"});
console.log('loading white bg');
}
if(lightmodeOn == false) {
// you can call your darkmode function here if want to set other things too.
$('body').css({background: "#0a0a0a"});
console.log('loading black bg');
}
}
function toggle() {
lightmodeOn = !lightmodeOn;
changeColorOfBackground(lightmodeOn);
localStorage.themepref = lightmodeOn?1:2;
}
document.addEventListener("DOMContentLoaded", function() {
//if it is not set in localStorage only then check OS theme otherwise always load from localStorage
if(localStorage.themepref === null) {
//if windows is light, then we should go with dark theme
if (window.matchMedia('(prefers-color-scheme: light)').matches) {
lightmodeOn = false;
}
}
else if (localStorage.themepref == 2 ) {
lightmodeOn = false;
}
if(lightmodeOn) {
$('#toggleCheck').prop('checked',true);
}
changeColorOfBackground(lightmodeOn);
});
</script>
</body>
</html>

Related

JS dark theme not changing

I'm trying to make light/light theme for a table in my project,its dark by default so i'm trying to change it to light when i click on the button but when i click it changes to light but not turning back any hints ?
var element = document.getElementById('toggleTheme')
var attributeContent = element.getAttribute('data-layout-mode')
let toggleTheme = document.querySelector(".light-dark-mode");
let styleSheet = document.querySelector("#color-theme");
console.log(attributeContent);
if (attributeContent=="dark") {
toggleTheme.addEventListener("click", () => {
styleSheet.setAttribute("href", "")
})
} else if (attributeContent=="light") {
toggleTheme.addEventListener("click", () => {
styleSheet.setAttribute("href", "{{ asset('css/style.css') }}")
})
} else {
console.log("not found")
}
You only define what to toggle based on the initial value of the attributeContent.
You should better do the test, on whether it is currently dark or light, each time the toggle is clicked.
something like
var element = document.getElementById('toggleTheme')
let toggleTheme = document.querySelector(".light-dark-mode");
let styleSheet = document.querySelector("#color-theme");
toggleTheme.addEventListener("click", function() {
// read the layout mode
var attributeContent = element.getAttribute('data-layout-mode');
if (attributeContent == "dark") {
styleSheet.setAttribute("href", "");
// set the layout mode to the new value
element.setAttribute('data-layout-mode', 'light');
} else if (attributeConten == "light") {
styleSheet.setAttribute("href", "{{ asset('css/style.css') }}");
// set the layout mode to the new value
element.setAttribute('data-layout-mode', 'dark');
} else {
console.log("not found")
}
})

Chrome extension on/off toggle button

I'm trying to create a button for my chrome extension that will toggle on/off the function of the extension. It's a simple AdBlock-style extension.
Currently, I have 4 scripts popup.js, popup.html, mainfest.json & background.js
For some reason I can't get this function if work, I've looked online at how other people have done this but couldn't get any of that to work either.
Any help would be great, either modifying my method or if there's a better way I'm unaware of!
Thanks!
Popup.js
var background = chrome.extension.getBackgroundPage();
var theButton = document.querySelector("button");
function updateButton(onOrOff){
theButton.innerHTML = onOrOff ? "Disable" : "Enable";
theButton.className = onOrOff ? "buttonOFF" : "buttonON";
}
function toggleButton(){
background.isExtensionOn = !background.isExtensionOn;
updateButton(background.isExtensionOn);
}
chrome.runtime.getBackgroundPage(function(backgroundpage) {
background = backgroundpage;
updateButton(backgroundpage.isExtensionOn);
theButton.onclick = toggleButton;
if (background.isExtensionOn == true){
alert("on");
}
if (background.isExtensionOn == false){
alert("off");
}
});
Background.js
var isExtensionOn = true;
popup.html
<button type="button1" class="button1" id="disableButton">Toggle</button>
<script src="popup.js"></script>
TIA!
By any chance have you looked into chrome storage? Haven't had much experience with getBackgroundPage, but here's my solution
background.js
chrome.runtime.onInstalled.addListener(() => {
chrome.storage.local.set({ 'onOrOff': true }, result => {
console.log("On Installed Set value to on")
})
})
var isExtensionOn = true;
chrome.storage.onChanged.addListener(function (changes, area) {
if (area === 'local' && changes.onOrOff) {
console.log(changes.onOrOff.newValue)
// extension is on
if (changes.onOrOff.newValue) {
isExtensionOn = true;
}
// extension is off
else {
console.log("Extension Is Off")
isExtensionOn = false;
}
}
})
popup.js
var theButton = document.querySelector("button");
function updateButton() {
// update button based on storage
chrome.storage.local.get(['onOrOff'], result => {
theButton.innerHTML = result.onOrOff ? "enabled" : "disabled";
theButton.className = result.onOrOff ? "buttonON" : "buttonOFF";
})
}
function toggleButton(e) {
// check className of button
var bool = e.target.className === 'buttonON' ? false : true
chrome.storage.local.set({ 'onOrOff': bool }, result => {
updateButton()
})
}
updateButton()
theButton.onclick = toggleButton
If you're interested in this solution, I would recommend looking into synchronous response to storage changes as well to make this cleaner. Also be sure to enable it in your permissions key in the manifest.json

Is there an any method to implement Night and Day mode on Static html site?

I need to implement Night/Day mode Functionality just like justanotherpanel website i don't have any database but i have admin panel where i write html css and javascript only
is there a way when user login and click on button website mode change into night mode by adding class and when they signout and login again night mode still on...?
ref site used this code
var mode = false ;
$('#nightmode').on('click', function() {
mode = !mode;
if (mode) {
$(this).removeClass('fa-moon-o');
$(this).addClass('fa-sun-o');
daymode = $('.daymode').removeClass('daymode');
daymode.addClass('nightmode');
$.get('/changevariable/custom_variable_1?value=2', function() {
});
} else {
$(this).removeClass('fa-sun-o');
$(this).addClass('fa-moon-o');
nightmode = $('.nightmode').removeClass('nightmode');
nightmode.addClass('daymode');
$.get('/changevariable/custom_variable_1?value=1', function() {
});
}
});
You can use localStorage to set the mode for a website. It'll be stored in the user's browser even after a reload.
$(document).ready(function(){
// Set the website mode when the page is loaded.
var mode = localStorage.getItem('theme');
// Set the selected theme if existing or else set the default theme.
if(mode !== null){
// Set the mode
if(mode == "light"){
$(this).removeClass('fa-moon-o');
$(this).addClass('fa-sun-o');
daymode = $('.daymode').removeClass('daymode');
daymode.addClass('nightmode');
} else if(mode == "night") {
$(this).removeClass('fa-sun-o');
$(this).addClass('fa-moon-o');
nightmode = $('.nightmode').removeClass('nightmode');
nightmode.addClass('daymode');
}
} else {
// If no modes are selected. Define a default mode.
$(this).removeClass('fa-moon-o');
$(this).addClass('fa-sun-o');
daymode = $('.daymode').removeClass('daymode');
daymode.addClass('nightmode');
localStorage.setItem("theme", "light")
}
})
$('#toggleThemeMode').on('click', function() {
var mode = localStorage.getItem('theme');
if(mode !== null){
// Toggle the selected modes.
if(mode == "night"){
$(this).removeClass('fa-moon-o');
$(this).addClass('fa-sun-o');
daymode = $('.daymode').removeClass('daymode');
daymode.addClass('nightmode');
localStorage.setItem("theme", "light")
} else if(mode == "light") {
$(this).removeClass('fa-sun-o');
$(this).addClass('fa-moon-o');
nightmode = $('.nightmode').removeClass('nightmode');
nightmode.addClass('daymode');
localStorage.setItem("theme", "night")
}
} else {
// If no modes are selected. Define a default mode.
$(this).removeClass('fa-sun-o');
$(this).addClass('fa-moon-o');
nightmode = $('.nightmode').removeClass('nightmode');
nightmode.addClass('daymode');
localStorage.setItem("theme", "night")
}
};

Adobe Edge HTML5 Local Connection

I`m trying to create two banners with adobeEdge and import them with iframes within 3rd file. So the structure would be something like this:
banner1.html
banner2.html
index.html (where banner1 and banner2 will be embed via iframe).
Those two banners will be animated, however file size, loading time of each may vary so they will not be loaded in the same time.
The problem is that I need them both to start playing in exact same time (in flash that is called local connection), so the idea is to check when both iframes are loaded and if each of them send DONE message to the other one I will play them.
I wrote a code which actually work, but still one banner always has a delay. Here is my code:
Banner 1
<script type="text/javascript">
var fr = window.parent.frames["frame2"];
var frwin = fr.contentWindow;
var otherLoaded = false;
var selfLoaded = false;
var process = setInterval(function(){load();},10);
window.addEventListener("message", receiveMessage, false);
function setLoaded(){
selfLoaded = true;
frwin.postMessage("Done", "DOMAIN");
}
function load(){
if(otherLoaded === true && selfLoaded === true){
clearInterval(process);
AdobeEdge.bootstrapCallback(function(compId) {
AdobeEdge.getComposition(compId).getStage().play();
});
}else if(selfLoaded === true && otherLoaded !== true){
frwin.postMessage("resend", "http://izorgor.com");
}
}
function receiveMessage(event) {
if (event.origin !== "DOMAIN")
return;
if(event.data === 'Done'){
otherLoaded = true;
console.log("Done");
}
if(event.data === 'resend'){
fr = window.parent.frames["frame2"];
frwin = fr.contentWindow;
frwin.postMessage("Done", "DOMAIN");
console.log("resend");
}
}
</script>
Banner 2
<script type="text/javascript">
var fr = window.parent.frames["frame1"];
var frwin = fr.contentWindow;
var otherLoaded = false;
var selfLoaded = false;
var process = setInterval(function(){load();},10);
window.addEventListener("message", receiveMessage, false);
function setLoaded(){
selfLoaded = true;
frwin.postMessage("Done", "DOMAIN");
}
function load(){
if(otherLoaded === true && selfLoaded === true){
clearInterval(process);
AdobeEdge.bootstrapCallback(function(compId) {
AdobeEdge.getComposition(compId).getStage().play();
});
}else if(selfLoaded === true && otherLoaded !== true){
frwin.postMessage("resend", "http://izorgor.com");
}
}
function receiveMessage(event) {
if (event.origin !== "DOMAIN")
return;
if(event.data === 'Done'){
otherLoaded = true;
console.log("Done");
}
if(event.data === 'resend'){
fr = window.parent.frames["frame1"];
frwin = fr.contentWindow;
frwin.postMessage("Done", "DOMAIN");
console.log("resend");
}
}
</script>
index.html
<iframe width="900" height="200" id="frame1" src="banner1.html" frameborder="0" scrolling="no"></iframe>
Thanks
I think you should contact your AdServer and ask if they are serving the Ad in just one TAG or in two TAGs
You can use libraries as https://github.com/jeremyharris/LocalConnection.js/tree/master
(similar to Flash Local Connection)
You can simply communicate between all your iframes in a window with a JavaScript library that I developed.
Get Documentation or Fork on GitHub. It uses nativ DOM to connect iframes with each other.
Sample usage :
include first LocalConnection script to all your banner. In this sample code we assume there are 2 banners need to communicate with each other. But it works also any number of banners.
in first banner :
<script>
LC.key = 'uniqueConnectionString';
LC.name = 'right'; // desc: my name is right and
LC.frames = 'left'; // I want to connect to the banner called left
LC.onConnect = function () {
console.log('Do this as soon as connection established!');
/*
From this point window of left and top will be available as
LC.left and LC.top
for example :
*/
LC.left.document.getElementsByTagName('body')[0].style.backgroundColor = 'pink';
};
</script>
On the second banner put the same code but change name and frames values like this :
<script>
LC.key = 'uniqueConnectionString';
LC.name = 'left'; // desc: my name is left and
LC.frames = 'right'; // I want to connect to the banner called right
LC.onConnect = function () {
console.log('Do this as soon as connection established!');
/*
From this point window of left and top will be available as
LC.left and LC.top
for example :
*/
LC.left.document.getElementsByTagName('body')[0].style.backgroundColor = 'pink';
};
LC.connect();
</script>

Why is the title and favicon of the window/tab not updating?

I'm playing around with jetpack to change the title (and ideally the favicon) of certain pages.
Firebug is showing that the HTML of the page has been changed correctly but Firefox just won't update the title of the window and/or tab.
This has to be possible, somehow, since Twitter Search is doing exactly that. It's updating the title as more search results show up, isn't it?
I guess I'm just missing something... any idea?
Example code as suggested in the comment:
function replaceTitle(doc)
{
if (doc.location.protocol == "http:" || doc.location.protocol == "https:")
{
var host=doc.location.host;
if(host.indexOf("stackoverflow.com")>=0)
{
var title=doc.getElementsByTagName("title")
console.log(title);
if(title)
{
var val=title[0];
if(val)
{
console.log("val", val);
console.log("valx", val.textContent);
val.textContent="Foo";
console.log("valz", val.textContent);
}
}
}
}
}
var state = "on";
function toggleState()
{
if( state == "off" )
{
jetpack.tabs.onReady(replaceTitle);
state = "on";
}
else
{
jetpack.tabs.onReady.unbind(replaceTitle);
state = "off";
}
console.log(state);
// This is a temporary way of keeping all browser window states
// in sync. We are working on a better API for this.
/*
widgets.forEach(function(widget) {
widget.defaultView.wrappedJSObject.setState(state);
});
*/
}
jetpack.statusBar.append(
{
html: "Boo",
onReady: function(widget)
{
console.log("ready");
// This is a temporary way of keeping all browser window states
// in sync. We are working on a better API for this.
/*
widgets.push(widget);
widget.defaultView.wrappedJSObject.setState(state);
*/
$(widget).click(toggleState);
},
onUnload: function(widget)
{
console.log("unload");
/*
widgets.splice(widgets.indexOf(widget), 1);
*/
},
width: 42
});
console.log("Test");
Irritatingly, it doesn't even show logs anymore since jetpack and firebug have been updated in the meantime :p
I'd expect this code to replace the title of stackoverflow.com pages with "Foo" - but this is just an example, replace stackoverflow.com with anything else if that might help, i.e. probably a site with less javascript magic than SO.com.
Update:
I solved the problem with the help of the answer below.
The working example looks like this:
function replaceTitle()
{
var doc=this.contentDocument;
console.log("replaceTitle "+ doc);
if(doc)
{
var location = doc.location;
if ( (location.protocol == "http:" || location.protocol == "https:")
&& location.host.indexOf("stackoverflow.com") !== -1 )
{
doc.title = "Foo";
console.log("Title set to "+doc.title);
}
else
{
console.log("Location "+location);
}
}
}
var state = "on";
function toggleState()
{
if( state == "off" )
{
state = "on";
jetpack.tabs.onReady(replaceTitle);
}
else
{
state = "off";
jetpack.tabs.onReady.unbind(replaceTitle);
}
console.log(state);
}
jetpack.statusBar.append(
{
html: "Boo",
onReady: function(widget)
{
console.log("ready: "+state);
$(widget).click(toggleState);
},
onUnload: function(widget)
{
console.log("unload");
},
width: 42
});
console.log("Testing");
might want to try
function replaceTitle(doc)
{
var location = doc.location;
if ( (location.protocol == "http:" || location.protocol == "https:")
&& location.host.indexOf("stackoverflow.com") !== -1 ) {
document.title = "Foo";
}
}
works for me
http://pastebin.me/4a3550e0dbe19?framepage
if you back down to firebug 1.4.0b4 it will fix that console problem you're having.
http://groups.google.com/group/mozilla-labs-jetpack/browse_thread/thread/c0cba73c67f19530#

Categories