I'm trying to persist checkbox state in a HTML (Flask/Jinja2) template using just html and CSS, but I've running into strange behavior where even though localStorage saves the state correctly, state is always set as true on load. I've looked up a ton of answers and have been stuck for a couple hours and I don't understand it isn't working:
HTML:
<input id="returnHeatmapsHtmlCheckbox"
type="checkbox" name="returnHeatmapsHtml" onclick="saveCheckboxState(this)" />
JS:
<script type="text/javascript">
window.onload = onPageLoad();
function onPageLoad (){
document.getElementById("returnHeatmapsHtmlCheckbox").checked = localStorage.getItem("returnHeatmapsHtmlCheckbox");
}
// <!-- Persist checkboxes -->
function saveCheckboxState(e){
var id = e.id
var val = e.checked
console.log("Saved value ID: " + id + ","+ val)
localStorage.setItem(id,val)
console.log("Loaded value ID: " + localStorage.getItem(id,val))
console.log(getSavedCheckboxState("returnHeatmapsHtmlCheckbox"))
}
function getSavedCheckboxState(v){
const default_dict = {
"returnHeatmapsHtmlCheckbox": false
};
if (!localStorage.getItem(v)) {
return default_dict[v];// return false by default.
};
return localStorage.getItem(v);
}
</script>
Any help would be greatly appreciated, thank you !
I reviewed your code and took the liberty to refactor some excerpts, I tried to keep it as similar as possible to what you did, you can see the result below.
HTML:
<input id="myCheckbox" type="checkbox" name="myCheckbox" />
JS:
// get the checkbox element
const myCheckbox = document.querySelector('#myCheckbox')
// responsible for setting a value in localStorage
// following the "checked" state
const setStorageState = (e) => {
const { id, checked } = e.target
localStorage.setItem(id, checked)
}
// responsible for searching and converting to Boolean
// the value set in localStorage
const getStorageState = (storageName) => {
return localStorage.getItem(storageName) === 'true'
}
// responsible for changing the state of your checkbox
const setCheckboxStateOnLoad = () => {
myCheckbox.checked = getStorageState('myCheckbox')
}
// calls the function "setStorageState" every time
// the user clicks on his checkbox
myCheckbox.addEventListener('click', setStorageState)
// calls the "setCheckboxStateOnLoad" function
// after the DOM content is loaded
document.addEventListener('DOMContentLoaded', setCheckboxStateOnLoad)
Hope it helps and sorry for the bad english :)
Related
I got this Code:
const odleglosc = parseFloat(document.getElementsByClassName("dystans")[0].innerText);
const daleko = "za daleko";
if (odleglosc > 200) {
alert(daleko);
}
<span data-pafe-form-builder-live-preview="lechnarlok" class="dystans" id="dystans">500</span>
It runs fine, because at starting point there is number higher than 200 in it.
But when i change it, alert don't trigger again..
How can i solve that? :(
Im not sure about how the span value will change, so this example works with an input. The same idea could also be applied to a span tho.
<input onchange="theFunction()" data-pafe-form-builder-live-preview="lechnarlok" class="dystans" id="dystans" value="500"></input>
<script>
function theFunction() {
var odleglosc = parseFloat(document.getElementsByClassName("dystans")[0].value);
var daleko = "za daleko";
if (odleglosc > 200)
{
alert(daleko);
}
}
</script>
Here, onChange calls the function whenever the value in the input field changes.
Do You want to show alert after each change of the value? If yes, use event listener for input (not for span).
Update:
Use MutationObserver for this case.
let span = document.getElementById('dystans');
function updateValue(value) {
var daleko = "za daleko";
if (parseFloat(value) > 200)
{
alert(daleko);
}
}
// create a new instance of 'MutationObserver' named 'observer',
// passing it a callback function
observer = new MutationObserver(function(mutationsList, observer) {
let value = mutationsList.filter(x => x.target.id =='dystans')[0].target.innerHTML;
updateValue(value);
});
// call 'observe' on that MutationObserver instance,
// passing it the element to observe, and the options object
observer.observe(span, {characterData: true, childList: true, attributes: true});
span.innerHTML = '3000';
<span data-pafe-form-builder-live-preview="lechnarlok" class="dystans" id="dystans">500</span>
Source:
Detect changes in the DOM
https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver
We are able to get a selection range via window.getSelection().
I'm wondering whether there is a way to subscribe to window.getSelection changes.
The only way which came to me is to use timeouts (which is obviously bad) or subscribe to each user's key \ mouse press event and track changes manually.
ANSWER UPD: You are able to use this library, I've published it, as there are no more suitable ones: https://github.com/xnimorz/selection-range-enhancer
Use the onselect event.
function logSelection(event) {
const log = document.getElementById('log');
const selection = event.target.value.substring(event.target.selectionStart, event.target.selectionEnd);
log.textContent = `You selected: ${selection}`;
}
const textarea = document.querySelector('textarea');
textarea.onselect = logSelection;
<textarea>Try selecting some text in this element.</textarea>
<p id="log"></p>
For specific cases such as span contenteditable, you can make a polyfill:
function logSelection() {
const log = document.getElementById('log');
const selection = window.getSelection();
log.textContent = `You selected: ${selection}`;
}
const span = document.querySelector('span');
var down = false;
span.onmousedown = () => { down = true };
span.onmouseup = () => { down = false };
span.onmousemove = () => {
if (down == true) {
logSelection();
}
};
<span contenteditable="true">Try selecting some text in this element.</span>
<p id="log"></p>
if Im undesrting in right way you want to know when user start selection on page you can use DOM onselectstart.
document.onselectstart = function() {
console.log("Selection started!");
};
more info MDN
I am working around a script that keeps one or multiple checkbox values checked on page reloaded or refreshed. The code below was executed to maintain the checkboxes values but it's not working. Any help will be appreciated.
<script>
function onClickBox() {
let checked=$("#check").is(":checked");
localStorage.setItem("checked", checked);
}
function onReady() {
let checked="true"==localStorage.getItem("checked");
$("#check").prop('checked', checked);
$("#check").click(onClickBox);
}
$(document).ready(onReady);
</script>
This line of code return '<input type="checkbox" id="check" href="#"' + 'order_id="'+ data + '">Yes</>'; allows admin to check a checkbox, after which the code takes the ID and then runs the check_payment.php that has the query that inserts yes to that ID row.
aoColumnDefs: [
{
aTargets: [6],
mData: "userId",
mRender: function (data, type, full) {
return '<input type="checkbox" id="check" href="#"' + 'order_id="'+ data + '">Yes</>';
//return '<button href="#"' + 'order_id="'+ data + '">Yes</button>';
}
}
],
language: {
url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/English.json'
}
});
$('#example').on( 'click', 'input:checkbox', function () {
var data = table.row( $(this).parents('tr') ).data();
var order_id = data['order_id'];
console.log(order_id);
$.ajax({
type: "POST",
url: 'check_payment.php',
data: "order_id=" + order_id,
});
} );
Here's a VanillaJS approach. We have document.querySelector now, so in my view, jQuery has been depreciated for a while. As far as I can tell your logic is solid, so I can only assume it's one of the jQuery calls that's breaking, and I honestly don't know which one.
// get element #check
var checkbox = window.check;
// checking and setting
isChecked = () => localStorage.getItem("checked") == "true";
setCheck = (v) => checkbox.checked = v;
// event handlers
onClickBox = () => localStorage.setItem("checked", checkbox.checked);
onReady = () => setCheck(isChecked());
// bindings
checkbox.addEventListener("click", onClickBox);
document.addEventListener("load", onReady);
Edit: I think what might be happening is the onLoad handler (or onReady, with jQuery) is never firing because the code is embedded in the body. If the script is in the head, use the eventHandler; if the script is in the body, just call onReady() after setting the click handler for the checkbox.
I am learning js, and I have a question that has confused me a little, I made a wrapper for the radiobutton, it is displayed in a modal window, and I want to transfer the value of the variable radiobutton to another function, tried it through var radioValue = $("input[name='radio']:checked").val();, but it retains the value that was when the page was loaded
$('input:radio[name=radio]').on('change', function () {
radioValue = $("input[name='radio']:checked").val();
});
(function(w,d,u,b){w['Bitrix24FormObject']=b;w[b] = w[b] || function(){arguments[0].ref=u;
(w[b].forms=w[b].forms||[]).push(arguments[0])};
if(w[b]['forms']) return;
var s=d.createElement('script');s.async=1;s.src=u+'?'+(1*new Date());
var h=d.getElementsByTagName('script')[0];h.parentNode.insertBefore(s,h);
})(window,document,'https://bistropechat.bitrix24.ru/bitrix/js/crm/form_loader.js','b24form');
b24form({"id":"5","lang":"ru","sec":"uwp5dl","type":"button","click":"", "presets": {"my_cookie1": "ValueChecked: " + radioValue }});
I have a js script that helps me create a cookie. It saves the checked checkboxes so this value is remembered (set in the cookie). Now the problem is that it doesn't seem to work with radio buttons. When reading the js-file, I see that input type=checkboxes. So it's logical it ignores radio buttons.
How do I change this script, so it will not only check the checked checkboxes, but also the checked radio buttons?
Many thanks
My js file script:
jQuery(document).ready(function(){
new chkRemembrance();
});
function chkRemembrance(){
this.__construct();
}
chkRemembrance.prototype = {
__construct : function(){
this.chk = this.fetchData(); // initialise array to store the checkboxes
this.init();
},
init : function(){
// first initialise all checkboxes that are checked
for(c in this.chk){
$("input[type=checkbox]#" + c).attr('checked', this.chk[c]);
}
// now make sure we fetch the checkbox events
var o = this;
$("input[type=checkbox]").change(function(){
o.saveData(this.id, this.checked);
})
},
fetchData : function(){
var r = {};
if ($.cookie('chk')){
r = JSON.parse($.cookie('chk'));
}
return r;
},
saveData : function(id,status){
this.chk[id] = status;
$.cookie('chk', JSON.stringify(this.chk));
}
}
It looks like you should just be able to add in the radio buttons and it will work.
Change this:
$("input[type=checkbox]#" + c).attr('checked', this.chk[c]);
To this:
$("input[type=checkbox]#" + c + ", input[type=radio]#" + c).attr('checked', this.chk[c]);
And change this:
$("input[type=checkbox]").change(function(){...});
To this:
$("input[type=checkbox], input[type=radio]").change(function(){...});