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
Related
How to preserve the navigation bar (minimized position) when navigated to other module.
Collapsed Navigation Bar
sidebar-collapse will not preserve if navigated to other page.
Do you want your nav-bar to change from big to small when you move to a different place?
(sorry, I'm not allowed to comment yet).
Do you want your nav-bar to change from big to small when you move to a different place? It is always nice if you add some code :)
const menuToggle = document.querySelector('.menu-toggle');
const mainUl = document.querySelector(".main-ul");
const navBtn = document.querySelectorAll(".nav-a");
// Open and close meny on click
menuToggle.addEventListener("click", function () {
menuToggle.classList.toggle("open");
mainUl.classList.toggle("open");
});
// Close menu when clicked on an a-tag in the menu
navBtn.forEach((button) => {
button.addEventListener("click", function () {
navBtn.forEach((button) => button.classList.remove("active"));
this.classList.add("active");
mainUl.classList.toggle("open");
menuToggle.classList.toggle("open");
});
});
This is demo and source code I created
https://minhhungit.github.io/2020/10/16/011-keep-menu-toggle-state-after-page-reload/
namespace J {
export function storageSet(name, val) {
if (typeof (Storage) !== "undefined") {
localStorage.setItem(name, val);
} else {
//window.alert('Please use a modern browser to properly view this template!');
}
}
export function storageGet(name) {
if (typeof (Storage) !== "undefined") {
return localStorage.getItem(name);
} else {
return null;
}
}
}
In _Layout.cshtml put this code
<script type="text/javascript">
$().ready(function () {
new DailyTimelog.Common.SidebarSearch($('#SidebarSearch'), $('#SidebarMenu')).init();
// ...
// ...
$(window).bind("load resize layout", doLayout);
doLayout();
});
</script>
// Add these lines
<script type="text/javascript">
let sidebarToggleButton = $('.main-header .sidebar-toggle');
if (sidebarToggleButton) {
$(sidebarToggleButton).on('click', function (e) {
e.preventDefault();
let isSidebarCollapse = $('body').hasClass('sidebar-collapse');
J.storageSet('IS_SIDEBAR_COLLAPSE', !isSidebarCollapse);
});
}
</script>
And LeftNavigation.cshtml
<script type="text/javascript">
function openWindow(url, width, height) {
height = height || (screen.availHeight - 60);
// ...
// ...
}
// Add these lines
let isSidebarCollapseCache = J.storageGet('IS_SIDEBAR_COLLAPSE');
if (isSidebarCollapseCache == 'true') {
$('body').toggleClass('sidebar-collapse', true);
}
else {
$('body').toggleClass('sidebar-collapse', false);
}
</script>
``
#minhhungit Thank you for your demo.
I have used cookie implementation similar to ThemePreference.
Views/Shared/_Layout.cshtml
var theme = !themeCookie.IsEmptyOrNull() ? themeCookie : "blue";
// Add following lines
var sbNavCookie = Context.Request.Cookies["SBNavigationPreference"];
var sbNav = !sbNavCookie.IsEmptyOrNull() && sbNavCookie == "true" ? true : false;
in Body Tag,
<body ... class="...#(sbNav?" sidebar-collapse":"")">
In Script Tag,
<script type="text/javascript">
$().ready(function () {
// Add new lines
let sidebarToggleButton = $('.main-header .sidebar-toggle');
if (sidebarToggleButton) {
$(sidebarToggleButton).on('click', function (e) {
e.preventDefault();
let isSidebarCollapse = $('body').hasClass('sidebar-collapse');
$.cookie('SBNavigationPreference', !isSidebarCollapse, {
path: Q.Config.applicationPath,
expires: 365
});
});
}
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>
I make chrome extension.
this program read now page and anlysis it, go to next page.
I already made read and goto next page. but there a problem.
read now page and move next page is perfect. but next page, read function isn't work.
I click read button on first page, read it. but move next and read, not work.
i see callback function get undefined data.
below is my code.
function matching(user) {
JustFIDsFromPage();
}
function JustFindIDsFromPage() {
//read and find Data
chrome.tabs.executeScript({
code: "var ids = [];var names = document.querySelector('.gallery').children;for(var i=0;i<names.length;i++){var tmp = names[i].innerHTML;var id = tmp.substring(11+tmp.search('/galleries/'),tmp.search('.html'));ids.push(id)} ids"
}, callbackJustFindIDsFromPage);
}
function callbackJustFindIDsFromPage(count) {
//save get datas.
var idList = count.toString().split(',');
for (var i = 0; i < idList.length; i++) {
document.querySelector('#result').innerText += idList[i] + "\n";
}
//go to next page.
chrome.tabs.executeScript({
code: "var page = document.querySelector('.page').firstElementChild.children; var end=0; var inhtml = page[1].innerHTML;var intext = page[1].innerText; if(inhtml == intext){var link = page[2].innerHTML; var url = link.substring(9, 20); end=1; window.location.href = url; } end;"
}, callbackGoNextPage);
}
function callbackGoNextPage(nextFlag) {
if (nextFlag == 1) {
JustFindIDsFromPage();
}
}
I guess this.
chrome.tabs.executeScript just excute on 'first' open page.
I don't know what is real. please help me!
this code will work for you.
chrome.tabs.getSelected(null, function (tabss) {
tabid = tabss.TAB_ID_NONE;
});
chrome.tabs.update(tabid, { url: url, active: true }, function (tab1) {
var listener = function (tabId, changeInfo, tab) {
if (tabId == tab1.id && changeInfo.status === 'complete') {
chrome.tabs.onUpdated.removeListener(listener);
//your code
}
}
chrome.tabs.onUpdated.addListener(listener);
});
Hi All I am trying to write both an if/else statement along with toggling an image. Basically my goal is to toggle an image (in this case with an id of soundonoff). However I can't seem to figure out where I am going wrong. The issue is the toggle works, but the detect of whether its muted or not does not work. (In my full code for example I have it switch innerHTML of various audio/video files, this is where document.getElementsByName('mymedia')[0] comes in. Any help would be tremendously appreciated I have spent about 4 hours working on this and can't seem to figure it out.
I should add that I do not know where to add an eventlistener for detectmute(), I tried to add it to my video, and to the button soundonoff but neither got working yet.
Here is my code:
function detectmute(){
if(document.getElementById('soundonoff').src == 'images/icons/soundoff.png'){
document.getElementsByName('mymedia')[0].muted = true;
}
else if(document.getElementById('soundonoff').src == 'images/icons/soundon.png'){
document.getElementsByName('mymedia')[0].muted = false;
}
$("#soundonoff").toggle(function(){
this.src = "images/icons/soundoff.png";
document.getElementsByName('mymedia')[0].muted = true;
}, function() {
this.src = "images/icons/soundon.png";
document.getElementsByName('mymedia')[0].muted = false;
});
}
Well I solved my own issue, Solution was the following:
$("#soundonoff").toggle(function(){
this.src = "images/icons/soundoff.png";
document.getElementsByName('mymedia')[0].muted = true;
$("#soundonoff").attr('name', 'soundoff');
}, function() {
this.src = "images/icons/soundon.png";
document.getElementsByName('mymedia')[0].muted = false;
$("#soundonoff").attr('name', 'soundon');
});
function detectmute(){
var soundstate = document.getElementById('soundonoff');
if (soundstate.name == "soundon")
{
document.getElementsByName('mymedia')[0].muted = false;
}
else if (soundstate.name == "soundoff")
{
document.getElementsByName('mymedia')[0].muted = true;
}
}
$('#soundonoff').on('click', function () {
var $this = $(this);
if ($this.attr('src') == 'images/icons/soundon.png') {
$this.attr('src', 'images/icons/soundoff.png').attr('data-muted', true);
} else {
$this.attr('src', 'images/icons/soundon.png').attr('data-muted', false);
}
});
Here is a demo: http://jsfiddle.net/jLvZW/3/ updated
You could also setup an object that converts one source to another:
var convert = {
'images/icons/soundon.png' : ['images/icons/soundoff.png', true],
'images/icons/soundoff.png' : ['images/icons/soundon.png', false]
};
$('#soundonoff').on('click', function () {
var $this = $(this);
$this.attr('src', convert[$this.attr('src')][0]).attr('data-muted', convert[$this.attr('src')][1]);
});
Here is a demo: http://jsfiddle.net/jLvZW/2/ Updated
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#