Getting my last clicked buton to store in local storage - javascript

I am creating an google chrome extension and I'm trying to create a start/ stop button. For some reason when I click the stop button, it will go to the start button while on the popup but when I exit off the popup, it resets back to the other button
Im trying to get my last clicked button to store in local storage so that when i click off the extension popup it will still show the button that was opposite of last clicked. For some reason when my stop button is clicked, it doesn't seem to store the variable lastclicked in local storage
Do anyone know what the issue may be or how to resolve this?
//Start and Stop buttons for logging
const btnStart = document.getElementById("click-start");
const btnStop = document.getElementById("click-stop");
//attempt to get start/stop logging buttons to work--underwork
function Logger(isLogging) {
let logger =''
if (isLogging){
btnStart.style.display= "none";
btnStop.style.display= "block";
logger = 'logging'
addRow();
} else {
btnStart.style.display= "block";
btnStop.style.display= "none";
logger = 'not logging'
}
//using storage API to save data for last btn pressed--underwork
chrome.storage.local.set({key: logger}, function() {
console.log('value is set to ' + logger);
});
}
var lastClicked = btnStart;
//button to start/stop logging
document.addEventListener("DOMContentLoaded", function () {
//get lastClicked first to make decisons
chrome.storage.local.get({'lastClicked': lastClicked}, function(result) {
if (result = btnStart) {
//works
btnStart.style.display= "none";
btnStop.style.display= "block";
console.log("last clicked is start button");
addRow();
} else if (result = btnStop) {
//not working
btnStart.style.display= "block";
btnStop.style.display= "none";
console.log("last clicked is stop button");
} else {
console.log("else statement");
}
//works
btnStart.addEventListener("click", function() {
Logger(true);
chrome.storage.local.set({'lastClicked': lastClicked}, function() {
lastClicked = btnStart; //doesnt know if it saves
console.log('logging started successful');
});
});
//works
btnStop.addEventListener("click", function() {
Logger(false);
chrome.storage.local.set({'lastClicked': lastClicked}, function() {
lastClicked = btnStop; // doesnt know if it saves
console.log('logging stopped successful');
});
});
});
chrome.storage.local.get(['key'], function(result) {
console.log('value currently is ' + result.key);
});

First, try to fix if (result = btnStart), you assign btnStart to result and it's always true if btnStart exists.
Change with if (result === btnStart) or if (result == btnStart)
Same thing for (result = btnStop)
Edition
I've spent some time to understand what you try to achieve and by reading the storage doc for extensions.
I think this code is really more readable
document.addEventListener("DOMContentLoaded", function () {
//Don't care about which button is used, keep the logica idea... is it started?
let started = true;
//Wait for content loaded before getting element is a better idea.
const btnStart = document.getElementById("click-start");
const btnStop = document.getElementById("click-stop");
//Keep all the logic together
const setStarted = s => {
started = s;
//This is a asynchronous call, I putted everything on the callback but as you want
chrome.storage.local.set({started: started}, () => {
console.debug("Storing `started` to storage with value:", isStarted);
btnStart.style.display = started? "none" : "block";
btnStop.style.display = !started? "block" : "none";
if ( started ) {
//What's that?
addRow();
}
});
};
//Get seems to by used with a string key, not an object
chrome.storage.local.get(['started'], (result) => {
console.debug("Reading `started` from storage gives", result.started);
//Using setStarted avoid repeting always the same thing
setStarted(result.started);
});
btnStart.addEventListener("click", () => setStarted(true) );
btnStop.addEventListener("click", () => setStarted(false) );
});

Related

Is there a way to add a function to my current button?

I am using JS and HTML. I have a button that displays the next section of html, but I wanted to add an additional function.
// Display Thanks Message
document.addEventListener('DOMContentLoaded', ()=>{
document.getElementById("btn").addEventListener("click", addPerson function() {
q5.style.display = "none";
end.style.display = "block";}
});
In this addPerson is the function I am trying to include. In this current code I keep getting syntax errors.
Call addPerson() inside the function.
// Display Thanks Message
document.addEventListener('DOMContentLoaded', () => {
document.getElementById("btn").addEventListener("click", function() {
addPerson();
q5.style.display = "none";
end.style.display = "block";
}
});
});

Pop up removed completly from DOM

I have created the below function that uses bootstrapalert where a pop up comes up that holds random data from a database table. But after I trigger the event and close the window I need to refresh the page in order for it to work again. I don't seem to find the issue in the code that causes this problem. Any suggestions for improvement?
<script>
var alertList = document.querySelectorAll(".alert");
alertList.forEach(function (alert) {
new bootstrap.Alert(alert);
});
function randomName() {
if (
document.getElementById("randomNamePopUp").dataset.showned == "false"
) {
document.getElementById("randomNamePopUp").style.display = "block";
document.getElementById("randomNamePopUp").dataset.showned = "true";
} else {
//window.location.href=window.location.href+"?showRandom=true";
}
}
const urlParams1 = new URLSearchParams(window.location.search);
const myParam = urlParams1.get("showRandom");
if (myParam == "true") {
randomName();
}
</script>

Avoid numbers incrementing multiple times when calling a function multiple times

I have written a quantity selector function to display on a page. The page can open some modals, which need to have another quantity selector within each.
I am calling the function within the main page, and also within the modal (to enable the functionality once the modal is displayed.)
When I adjust the quantity in the modal, close the modal, and adjust the quantity on the main page, the quantity increments/decrements double (or 3 times if I was to call the function 3 times.)
Is there a way to "reset" each of these event listeners/functions, to only adjust for their respective elements?
I've looked into "removeEventListener" but haven't had any joy in implementing this within my code.
Example of my work so far here (you can see what I mean if you click the buttons.)
https://codepen.io/777333/pen/zYoKYRN
const quantitySelector = () => {
const qtyGroups = document.querySelectorAll('.qty-group');
if(qtyGroups) {
qtyGroups.forEach((qtyGroup) => {
const qtyDecrease = qtyGroup.querySelector('[data-quantity-decrease]');
const qtyIncrease = qtyGroup.querySelector('[data-quantity-increase]');
const qtyInput = qtyGroup.querySelector('[data-quantity-input]');
const disableEnableDecrease = () => {
if(qtyInput.value == 1) {
qtyDecrease.disabled = true;
} else {
qtyDecrease.disabled = false;
}
};
qtyDecrease.addEventListener('click', (event) => {
event.preventDefault();
if(qtyInput.value > 1) {
qtyInput.value--;
}
disableEnableDecrease();
});
qtyIncrease.addEventListener('click', (event) => {
event.preventDefault();
qtyInput.value++;
disableEnableDecrease();
});
qtyInput.addEventListener('keyup', () => {
disableEnableDecrease();
});
});
}
};
quantitySelector(); // called within main page
quantitySelector(); // called within modal
The issue at hand is that each time you're calling the function, a new event handler is added on top of the previous ones. The best way to avoid this is through Event Delegation where you add a global event handler only once.
// A global event handler
document.addEventListener(
"click",
function (event) {
// Find the qty-group if clicked on it
const qtyGroup = event.target.closest(".qty-group");
// Stop if the click was elsewhere
if (qtyGroup) {
// Get your elements
const qtyDecrease = qtyGroup.querySelector("[data-quantity-decrease]");
const qtyIncrease = qtyGroup.querySelector("[data-quantity-increase]");
const qtyInput = qtyGroup.querySelector("[data-quantity-input]");
const disableEnableDecrease = () => {
if (qtyInput.value == 1) {
qtyDecrease.disabled = true;
} else {
qtyDecrease.disabled = false;
}
};
// Match your elements against what was clicked on.
if (event.target == qtyDecrease) {
event.preventDefault();
if (qtyInput.value > 1) {
qtyInput.value--;
}
disableEnableDecrease();
}
if (event.target == qtyIncrease) {
event.preventDefault();
qtyInput.value++;
disableEnableDecrease();
}
}
},
false
);
Instead of listening to individual elements, you can capture all the clicks on the document, and then finding those that click on elements of interest. You can make a second event handler for the keyup event.
You can save the value of qtyInput on mousedown event and then in the increment you add or subtract one from the saved value instead of the current value of the input.
const quantitySelector = () => {
const qtyGroups = document.querySelectorAll('.qty-group');
if(qtyGroups) {
qtyGroups.forEach((qtyGroup) => {
const qtyDecrease = qtyGroup.querySelector('[data-quantity-decrease]');
const qtyIncrease = qtyGroup.querySelector('[data-quantity-increase]');
const qtyInput = qtyGroup.querySelector('[data-quantity-input]');
const disableEnableDecrease = () => {
if(qtyInput.value == 1) {
qtyDecrease.disabled = true;
} else {
qtyDecrease.disabled = false;
}
};
let savedValue = null;
const saveState = (evebt) => savedValue = Number(qtyInput.value);
qtyDecrease.addEventListener('mousedown', saveState)
qtyIncrease.addEventListener('mousedown', saveState)
qtyDecrease.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
if(qtyInput.value > 1) {
qtyInput.value = savedValue - 1;
}
disableEnableDecrease();
});
qtyIncrease.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
qtyInput.value = savedValue + 1;
disableEnableDecrease();
});
qtyInput.addEventListener('keyup', () => {
disableEnableDecrease();
event.stopPropagation();
});
});
}
};
quantitySelector();
quantitySelector();
There is a method called removeEventListener (MDN) but I suggest you to reshape your code such that you do not add event listener if they are already present.
Put all of your addEventListener just when you create your elements, or in a "document ready" callback if they are instantiated by HTML code. Then, when you open your modal, just update your values.
UPDATING YOUR CODE
// hide/show modal function
function toggleModal() {
let modal = document.getElementById('modal');
modal.style.display = modal.style.display == 'none' ? 'block' : 'none';
}
// your document ready function
function onReady() {
const qtyGroups = document.querySelectorAll('.qty-group');
if(qtyGroups) {
qtyGroups.forEach((qtyGroup) => {
const qtyDecrease = qtyGroup.querySelector('[data-quantity-decrease]');
const qtyIncrease = qtyGroup.querySelector('[data-quantity-increase]');
const qtyInput = qtyGroup.querySelector('[data-quantity-input]');
const disableEnableDecrease = () => {
if(qtyInput.value == 1) {
qtyDecrease.disabled = true;
} else {
qtyDecrease.disabled = false;
}
};
qtyDecrease.addEventListener('click', (event) => {
event.preventDefault();
if(qtyInput.value > 1) {
qtyInput.value--;
}
disableEnableDecrease();
});
qtyIncrease.addEventListener('click', (event) => {
event.preventDefault();
qtyInput.value++;
disableEnableDecrease();
});
qtyInput.addEventListener('keyup', () => {
disableEnableDecrease();
});
});
}
// attach hide/show modal handler
const toggle = document.getElementById('modal_toggle');
toggle.addEventListener('click', toggleModal);
}
onReady();
<div class="qty-group">
<button data-quantity-decrease disabled>-</button>
<input data-quantity-input value="1">
<button data-quantity-increase>+</button>
</div>
<div class="qty-group" id="modal" style="display: none;">
<button data-quantity-decrease disabled>-</button>
<input data-quantity-input value="1">
<button data-quantity-increase>+</button>
</div>
<button id="modal_toggle">Toggle Modal</button>
REFACTORING
It is better in such cases to reason as Components. Components ensure code encapsulation, maintainability, reusage, single responsability and many other usefull principles:
// hide/show modal function
function toggleModal() {
// get the modal
let modal = document.getElementById('modal');
// hide the modal
modal.style.display = modal.style.display == 'none' ? 'block' : 'none';
// reset the input of the modal
modalInputReference.reset();
}
function createQuantityInput(target, initialQuantity=1, min=1, max=10, step=1) {
let quantity = 0;
// assign and check if should be disable, also bind to input value
let assign = (q) => {
quantity = Math.max(Math.min(q, max), min);
decrease.disabled = quantity <= min;
increase.disabled = quantity >= max;
input.value = quantity;
};
// CREATION
// This part is not mandatory, you can also get the elements from
// the target (document.querySelector('button.decrease') or similar)
// and then attach the listener.
// Creation is better: ensure encapsulation and single responsability
// create decrease button
let decrease = document.createElement('button');
decrease.addEventListener('click', () => { assign(quantity - step); });
decrease.innerText = '-';
// create increase button
let increase = document.createElement('button');
increase.addEventListener('click', () => { assign(quantity + step); });
increase.innerText = '+'
// create input field
let input = document.createElement('input');
input.value = quantity
input.addEventListener('change', () => { assign(parseFloat(input.value)); });
// resetting the quantity
assign(initialQuantity);
// appending the new component to its parent
target.appendChild(decrease);
target.appendChild(input);
target.appendChild(increase);
// return a reference to manipulate this component
return {
get quantity() { return quantity; },
set quantity(q) { assign(q); },
assign,
reset: () => assign(initialQuantity)
};
}
// this will be your modal reference
let modalInputReference;
function onReady() {
// inject all qty-group with a "quantityInput" component
document.querySelectorAll('.qty-group').forEach(elem => {
let input = createQuantityInput(elem);
if (elem.id == 'modal') {
// if it is the modal I save it for later use
// this is just an hack for now,
// a full code should split this part into a "modal" component maybe
modalInputReference = input;
}
});
// emualte the modal
let toggle = document.getElementById('modal_toggle')
toggle.addEventListener('click', toggleModal)
}
// this function should be wrapped by a
// $(document).ready(onReady) or any other
// function that ensure that all the DOM is successfully loaded
// and the code is not executed before the browser has generated
// all the elements present in the HTML
onReady();
<div class="qty-group"></div>
<div class="qty-group" id="modal" style="display: none;"></div>
<button id="modal_toggle">Toggle Modal</button>
It is shorter (without comments) and also more maintenable. Don't trust who says it is overengineered, it is just kind of time to learn to reason this way, then is much easier and faster. It is just a time investment to waste less time in the future. Try figure out why React or Angular(JS) have climbed the charts of the best frameworks so fast.

disclose the alert button using javascript

In my project, I've added the alert box and try to close the box if the user clicks on disclose button. But I don't know why this if condition is not executed.
can anyone tells me where I did make a mistake?
window.onload = function(){
var button = document.querySelector(".close");
var successMessage = document.querySelector(".messageStackSuccess");
var messageStack = document.querySelector(".messageStackError");
// console.log(successMessage.className);
button.onclick = function () {
if (messageStack.className == "messageStackError") {
messageStack.classList.add("displayNone");
}
else if (successMessage.className == "messageStackSuccess") {
successMessage.classList.add("displayNone");
}
};
};

Timer in Javascript while functions

I have this code:
input.addEventListener('keydown', (event) => {
if (event.keyCode === 13 && input.value) {
sendText(input.value);
var response = responseChat(input.value, 'user');
insertResponse(response);
input.value = '';
}
});
In this code, the client types some words to send to app web. So, I need when, the client not type and send some, the page sends a message of: "You are not work!!"
I create this function with setTimeOut but I don't know how to put this in my code:
function first(){
sendText("your are not work!");
}
function sendFirst(){
clearTimeout(time);
time = setTimeout(first, 5000);
}
Could you help me? Thanks
This is what you want. Will console.log 'you are not working!' after 3 seconds of keyboard inactivity. Click 'Run code snippet' below to try it out.
const sendText = console.log;
const input = document.getElementById('fred');
let timeout
const restart = () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
sendText("you are not working!");
}, 3000);
}
restart();
input.addEventListener('keydown', (event) => {
restart();
if (event.keyCode === 13 && input.value) {
sendText(input.value);
// var response = responseChat(input.value, 'user');
// insertResponse(response);
input.value = '';
}
});
<input id="fred">

Categories

Resources