I have toggle on the options page which should show / hide div on another page. With some help here on stack I was able to structure this code, but I can't get it to work.
Fiddle: https://jsfiddle.net/snake93/mLonrbkf/1/
I can't show / hide the divs
I don't understand how to save in localstorage
I would like to understand what values the functions of the Js code must assume. Can anyone help me?
function setSetting(name,value){
window.localStorage.setItem(name,true);
}
function getSetting(name){
return window.localStorage.getItem(name);
}
const div = document.querySelector("label-ck1");
if(getSetting("show")){
div.style.display = "block";
}
else{
div.style.display = "none";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<label class="switch">
<input type="checkbox" id="ck1">
<span class="slider round hide-off"></span>
</label>
<br><br>
<label class="switch">
<input type="checkbox" id="ck2">
<span class="slider round hide-off"></span>
</label>
<br><br>
<div class="hideme" id="label-ck1">Please hide me...</div>
<div class="hideme" id="label-ck2">Please hide me...</div>
I copied what you wrote in your original code in jsfiddle using the same css I found there. Then I just rewrote the javascript part.
What it does is attaching a change event handler to any checkbox found on the page so that when their state it's changed, the corresponding label gets shown or hidden. The corresponding label is found using the checkbox id with the prefix label-.
In that event, the state of the checkbox changed gets pushed in the localStorage. At the very beginning, the page first checks if there's any state saved for each of the checkbox found and in case there is, its state gets updated correspondingly.
In Firefox localStorage methods (getItem/setItem) return SecurityError: The operation is insecure. I could run that code on a dedicated html page to verify it's working correctly (on Chrome for sure). So to avoid any problem at first, I added a securityFlag on top of the js code. When that flag is set to true, the localStorage won't be engaged at all so that you could see the preview here with no errors.
//if set to true, any operation involving localStorage will be excluded
let securityFlag = true;
/**
* Initialize the Checkboxes state according to what's stored on localStorage
*/
function initCheckboxStateBasedOnLocalStorage(){
//for each of the checkboxes on the page
document.querySelectorAll('input[type="checkbox"]').forEach( (checkbox, i) => {
//if securityFlag is true, skip the operation
if(securityFlag) return;
//retrieves the value stored in localStorage paired to the id passed
let valueStored = window.localStorage.getItem(checkbox.id);
//if valueStored is set
if(valueStored == 'true' || valueStored == 'false')
//sets the checkbox value with what was retrieved from localStorage
checkbox.checked = valueStored == 'true' ? true : false;
});
}
/**
* Will hide/show the label corresponding to checkbox and will save its value on localStorage
* It will be registered as the handler of the change event of every checkbox in the page
*/
function onCheckBoxStateChange(){
let checkbox = event.target;
//guesses the id of the label dedicated to the checkbox triggering the event
let msgContainer = document.getElementById(`label-${checkbox.id}`);
//if this checkbox is checked,
if (checkbox.checked){
//show the corresponding label
msgContainer.style.display = "block";
//if securityFlag is true, skip the operation
if(securityFlag) return;
//sets the state in localStorage for this.id
window.localStorage.setItem(checkbox.id ,true);
}
//otherwise
else{
//hide the corresponding label
msgContainer.style.display = "none";
//if securityFlag is true, skip the operation
if(securityFlag) return;
//sets the state in localStorage for this.id
window.localStorage.setItem(checkbox.id ,false);
}
}
//When the document has been loaded
document.addEventListener("DOMContentLoaded", function() {
//for each of the checkboxes on the page
document.querySelectorAll('input[type="checkbox"]').forEach( (checkbox, i) => {
//attach an handler to the event change
checkbox.addEventListener("change", onCheckBoxStateChange );
});
});
//reflect the value of checkboxed according to what's stored on localStorage
initCheckboxStateBasedOnLocalStorage();
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
/*END OF TOGGLE SWITCH*/
.hideme {
padding:20px;
background: blue;
color: white;
font-weight: 800;
text-align: center;
}
<p>checkbox1</p>
<label class="switch">
<input type="checkbox" id="ck1">
<span class="slider round hide-off"></span>
</label>
<br><br>
<p>checkbox2</p>
<label class="switch">
<input type="checkbox" id="ck2">
<span class="slider round hide-off"></span>
</label>
<br><br>
<div class="hideme" id="label-ck1">Label bound to checkbox1</div>
<div class="hideme" id="label-ck2">Label bound to checkbox2</div>
In case you need a fully workable solution out of the box, I uploaded a set of files on pastebin as being:
File
Download link
demo.html
https://pastebin.com/mHWQ7564
style.css
https://pastebin.com/3jzTubFR
logic.js
https://pastebin.com/uFDrGrZx
Save them on your local computer inside the same folder and please make sure the filenames are exactly how I listed on that table. Then load the file demo.html from your web browser.
It's a slightly modified version of what I shared here. Its behavior is fully consistent with any initial condition. I also added, for the sake of further education, a strategy to add new checkbox-label pairs to the page programmatically.
There are buttons on top of the page to:
Add a new checkbox
Reset the local storage
Reload the page
There's a lot to digest there if you are not familiar with developing web pages yet. Good luck!
Related
I used some codes from google but the problem is when user click on heart it just animate but not able to count the value and not able to store the value in localstorage. I want to store the click count value in localstorage so that if user click on heart it will save the value in his browser after refreshing also his clicked value should be saved in his browser until an unless he retained the clicked value to remove the heart.
I am new in this please help me.
Below is the code
Jquery 3.5.1
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
HTML
<div class="heart"></div>
CSS
.heart {
width: 100px;
height: 100px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: url(http://imagizer.imageshack.com/img923/4545/XdJDuY.png) no-repeat;
cursor: pointer;
}
.heart-blast {
background-position: -2800px 0;
transition: background 1s steps(28);
}
Script
$(function() {
$(".heart").on("click", function() {
$(this).toggleClass("heart-blast");
});
});
first add a counter variable
let count;
then increase it by 1 in every click
$(function() {
$(".heart").on("click", function() {
count+=1;
$(this).toggleClass("heart-blast");
});
});
then save the variable to localStorage
$(function() {
$(".heart").on("click", function() {
count+=1;
$(this).toggleClass("heart-blast");
localStorage.setItem(count,"heartClicks");
});
});
to get the variable again from local storage use localStorage.GetItem
let clicks = localStorage.getItem("heartClicks");
I have button in html that is on the middle left of the screen, that button is styled such as:
.openbtn {
font-size: 20px;
border-radius: 0 5px 5px 0;
cursor: pointer;
position: fixed;
Top: 50%;
left: 0px;
background-color: #181A1B;
color: white;
padding: 10px 15px;
border: none;
z-index: 1;
transition: 0.5s;
}
now when i click this button i want it to transfer to the upper right and when i click again it should go back to its original position. In Javascript the button is handled as so:
var lastState = false;
function sideButtonClicked() {
if(!lastState){
//open
lastState=true
document.getElementById("Button").style.left = "";
document.getElementById("Button").style.right = "0";
document.getElementById("Button").style.top = "0";
}
else{
//close
lastState=false
document.getElementById("Button").style.left = "0px";
document.getElementById("Button").style.right = "";
document.getElementById("Button").style.top = "50%";
}
I find this tricking because if i want to play that button on the upper right corner is when i declare it on css i dont place the left property but since its initial position is in the left i have to declare it. I tried setting it to "" but it does not work. What i know works is the button moves up/down upon clicking the button,
}
This is a simple example of how to toggle classes in vanilla JS. Then, you just do your styling via CSS.
// Cache the DOM element for continued use
var btn = document.getElementById("btn");
// Attach event listener to button for 'click' event
btn.addEventListener("click", () =>
{
// Where we see if it has the class or not
// Is it inactive?
if (!btn.classList.contains("active"))
{
console.log("Added");
btn.classList.add("active");
} else // If it *is* currently active
{
console.log("Removed");
btn.classList.remove("active");
}
});
.btn {
padding: 1rem;
width: 200px;
transition: all 300ms ease-in-out;
}
.btn.active {
padding: 2rem;
width: 400px;
}
<button class="btn" id="btn">Click Me</button>
Essentially, you're using a CSS class as a target for the different styling and just using JS to turn the class on/off. That way, you can just edit the 'toggle' class in CSS to whatever you want and the code will always work. This is usually what we use for sticky navbars, etc. You just add/remove another class, and that overrides the default styling.
JS:
document.getElementsByTagName("input, select, textarea, option, optgroup, fieldset, label").onchange = function () {
var updateRate = document.querySelector('.updateRate');
updateRate.style.display = "block";
};
mark-up & styles:
<div class="updateRate">Update Rate</div>
<style>
.updateRate {
display:none;
top: 0px;
position: fixed;
width: 100%;
left: 0px;
z-index: 11111;
}
#rate, .updateRate {
background: #354563;
color: #ffffff;
cursor: pointer;
text-align: center;
padding: 10px;
}
</style>
The above is my attempt; but the banner is still not displaying after any form elements state change.
Update: So both SO answers below seem to be correct; but perhaps I didn't explain the context enough - now the 'banner' displays as soon as the form is beginning to be filled out the first time; the goal was for the banner to show after a user has gone back in and updated a form element (second time, or changing it from initial).
Context:
It is an inline quote tool; a quote will generate inline after form elements are filled out. I was trying to create a 'banner' that would que if a user has adjusted any web form element a second time. Sorry for the confusion.
You can't attach the event this way since the getElementsByTagName method accept one single tag name you could use the querySelectorAll() method instead to get the elements then loop through them using foreach and attach the event using addEventListener():
var fields = document.querySelectorAll("input, select, textarea, option, optgroup, fieldset, label");
[].forEach.call(fields, function(el) {
el.addEventListener('change', showUpdateRate, false);
});
function showUpdateRate() {
if (document.querySelector('.quote').textContent != "") {
document.querySelector('.updateRate').style.display = "block";
}
}
document.querySelector('.generate').addEventListener('click', function() {
var quote = document.querySelector('[name="type"]:checked').value;
document.querySelector('.quote').textContent = quote + " Quote";
});
.updateRate {
display: none;
top: 0px;
position: fixed;
width: 100%;
left: 0px;
z-index: 11111;
}
#rate,
.updateRate {
background: #354563;
color: #ffffff;
cursor: pointer;
text-align: center;
padding: 10px;
}
<div class="updateRate">Update Rate</div>
<br><br><br>
<form>
<input type="radio" name="type" value="Success">Success
<input type="radio" name="type" value="Motivation">Motivation
<input type="radio" name="type" value="Work">Work
<br><br>
<input type="button" class="generate" value="Generate">
</form>
<br>
<span class="quote"></span>
.getElementsByTagName() returns a node list (an array-like object), not a single element. As such, it doesn't have an onchange property to work with. After getting the node list, you'll need to loop over all the items in the list and set up the event handler for each, one at a time.
Also, .getElementsByTagName() only allows for a single tag name to be passed in, not a comma separated list. Additionally, it returns a "live node list", which has performance implications, so if you aren't dynamically adding/removing elements, you should avoid it and use .querySelectorAll() instead.
Now, option, optgroup, and label elements can only be changed via code, and don't emit or recieve a change event in the first place, so you actually don't want/need those included in your node list.
More comments about how to make your code more modern and organized inline below:
// Get this reference just once and cache it in a variable
var updateRate = document.querySelector('.updateRate');
// Gather up all the relevant elements into a node list
let elements = document.querySelectorAll("input, select, textarea, fieldset");
// Convert the node list into an Array so that .forEach()
// can safely be used to loop in all modern browsers
Array.prototype.slice.call(elements).forEach(function(element){
// Add event listeners the modern way, not with .onXyz properties
element.addEventListener("change", function () {
// Just remove the hidden class already applied to the element
// instead of working with inline styles
updateRate.classList.remove("hidden");
});
});
/*
This is applied to the "Update Rate" element in HTML by default.
It can be removed by the JavaScript when appropriate.
*/
.hidden { display:none; }
.updateRate {
top: 0px;
position: fixed;
width: 100%;
left: 0px;
z-index: 11111;
}
#rate, .updateRate {
background: #354563;
color: #ffffff;
cursor: pointer;
text-align: center;
padding: 10px;
}
<form>
<fieldset>
<legend>This is the legend</legend>
<input>
<select>
<option>choice 1</option>
<option>choice 2</option>
<option>choice 3</option>
</select>
</fieldset>
<textarea></textarea>
</form>
<!-- Set this element to be hidden by default -->
<div class="updateRate" class="hidden">Update Rate</div>
I have a form that uses very basic input validation using javascript onSubmit before the server side processing begins in PHP.
However, due to the time the PHP script takes to process (uploading images etc) I am trying to use the same onSubmit function to display a "please wait" notice if it passes validation. Or is there a better way? I tried in PHP, but the processing has to complete before I can echo any output. Anything I have tried from other SO posts stops the validation process.
<form id="form" method="post" action="" onsubmit="return Validate(this)" autocomplete="off">
Current Javascript Example
function Validate(myForm) {
var error = '';
// Example Filed
if(myForm.name.value == '') {
error += '- Please enter your Name.\n';
}
// Show Error Notice
if(error != '') {
error = 'The form has not been completed correctly, please check the following:\n\n' + error;
alert(error); // Displays Error
return false;
} else {
// Allows the form to move on to PHP Processing
// Need to Show Waiting Notice here
return true;
}
}
CSS & HTML Waiting Notice (Initially Hidden)
<style>
#processing {
display:block;
position: fixed;
top: 0;
left: 0;
background: rgba(255,255,255,0.8);
width: 100%;
height: 100%;
}
#popup {
width: 300px;
min-height: 160px;
padding:20px;
background-color: #fff;
border: 5px solid #06C;
text-align: center;
color: #202020;
position: absolute;
left: 50%;
top: 50%;
margin-left: -150px;
margin-top: -100px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
}
#popup img {
height:60px;
width:60px;
}
</style>
<div id="processing">
<div id="popup">
<img width="60" height="60" src="../waiting.gif" />
<h3>Please Wait!</h3>
<p>The form is processing...</p>
</div>
</div>
Any help would be appreciated
All you need to do is have the "...Please Wait..." element already present in the document, but hidden and then show it when the submit takes place. You do this by applying a CSS class to the element in the HTML, which hides it initially and then remove that class when the form is valid.
A couple of side notes...
Don't use inline HTML event attributes (onsubmit, onclick, etc.). That is how events were registered 20 years ago and there are many drawbacks to using them. Unfortunately, because most people just copy what others have done, the use of this approach just will not die. Instead, follow modern standards and use .addEventListener().
Also, don't ever name an element or a variable name as name is a property of the Global window object and the use of that name can cause problems in the code.
// Get references to the DOM elements that your code will need
var frm = document.getElementById("form");
var wait = document.getElementById("processing");
var userName = document.getElementById("txtName");
frm.addEventListener("submit", validate); // Set up events the modern, standards-based way
// All event handlers will automatically be passed a reference
// to the event object for that event
function validate(evt) {
var error = '';
// Example Filed
if(userName.value == '') {
error += '- Please enter your Name.\n';
}
// Show Error Notice
if(error != '') {
error = 'The form has not been completed correctly, please check the following:\n\n' + error;
alert(error); // Displays Error
evt.preventDefault(); // Stop the event
} else {
// Allows the form to move on to PHP Processing
// Need to Show Waiting Notice here
wait.classList.remove("hidden"); // Remove the hidden class
}
}
#processing {
display:block;
position: fixed;
top: 0;
left: 0;
background: rgba(255,255,255,0.8);
width: 100%;
height: 100%;
}
#processing.hidden { display:none } /* This hides the message by default */
#popup {
width: 300px;
min-height: 160px;
padding:20px;
background-color: #fff;
border: 5px solid #06C;
text-align: center;
color: #202020;
position: absolute;
left: 50%;
top: 50%;
margin-left: -150px;
margin-top: -100px;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
}
#popup img {
height:60px;
width:60px;
}
<form id="form" method="post" action="#" autocomplete="off">
<input type="text" id="txtName">
<input type="submit">
</form>
<div id="processing" class="hidden">
<div id="popup">
<img width="60" height="60" src="../waiting.gif" />
<h3>Please Wait!</h3>
<p>The form is processing...</p>
</div>
</div>
On your javascript validation, you could let the user know the image is loading by showing a simple message.
<div class="loading" style="display:none;">Loadin ...</div>
function Validate(myForm) {
var error = '';
// Example Filed
if(myForm.name.value == '') {
error += '- Please enter your Name.\n';
}
// Show Error Notice
if(error != '') {
error = 'The form has not been completed correctly, please check the following:\n\n' + error;
alert(error); // Displays Error
return false;
} else {
// Allows the form to move on to PHP Processing
// Need to Show Waiting Notice here
// show the user the image is loading
$('#form .loading').show();
return true;
}
}
After it loads you may remove the message once you get a response from the server.
$('#form .loading').hide();
I'm looking for some assistance with a website I'm coding. I have an HTML and CSS switch button (or label):
HTML:
<label class="switch">
<input type="checkbox"></input>
<div class="slider round"></div>
</label>
CSS:
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {display:none;}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
Here is just what the button looks like: https://jsfiddle.net/pbxn2egc/
Essentially what I want or am trying to do is when the button is toggled, I would like for it to show the price of 5 items (that I hard-coded in, so like standard html) and then when you toggle the button it hides that text and shows the competitors price by showing that text.
So if the button is left, I want Walmart's prices. If the button gets toggled to the right, Walmart's prices hide, and Target's appear in the same location.
Can someone assist me with this? Thanks!
One approach is to listen for the onchange event on your <input> element.
Then, when the box is checked/unchecked, you can determine which element (price) is visible and display the other.
document.getElementById("mySwitch").onchange = function() {
var priceA = document.getElementById("priceA");
var priceB = document.getElementById("priceB");
if (priceA.classList.contains("hidden")) {
priceA.className = "shown";
priceB.className = "hidden";
} else if (priceB.classList.contains("hidden")) {
priceB.className = "shown";
priceA.className = "hidden";
}
}
.shown {
}
.hidden {
display: none;
}
<input type="checkbox" id="mySwitch"></input>
<div class="slider round"></div>
<div id="priceA" class="shown">Price A</div>
<div id="priceB" class="hidden">Price B</div>
If you're using jQuery, there's a toggleClass() method that will automatically toggle an element between two classes.
function togglePrices() {
Array.from(document.querySelectorAll('.price')).forEach(function (f) {
f.classList.toggle('hidden');
});
}
.hidden {
display: none;
}
<input type="checkbox" onchange="togglePrices()"> Competitors Price
<div class="price">
<h3>Our Price</h3>
water $10.00<br/>
beer $12.00<br/>
wine $20.00
</div>
<div class="price hidden">
<h3>Competitors Price</h3>
water $12.00<br/>
beer $15.00<br/>
wine $24.00
</div>
In comparison with the answer from #rphv, this is how I would do it...
I have a div for pricing; within that is a div for our prices and another for their prices. The pricing container is unique on the page, and I give it an ID to signify its purpose.
I give the two price divs two classes each; they both get the class "price" and then either "ours" or "theirs", again to describe what they are (not how they look)
The HTML is now a descriptive structure of the data it contains, without bothering with appearance (because appearance is the job of CSS, not HTML)
We start off displaying our prices, so things with class "ours" are displayed when they are within the pricing div #pricing .price.ours; things with class "theirs" are not displayed #pricing .price.theirs.
Later, when the pricing div has class theirs we will show their prices, not ours — so let's hook up our toggle.
One should prefer attaching event handlers over using inline "onevent" javascript handlers, so I gave the checkbox an ID to easily select it, then use addEventListener so the change event will call togglePrices
The togglePrices could have been a one-liner, I only assigned the var because you often want to do several things with the selected element. Here I simply toggle the class "theirs" on and off.
What happens when that class is toggled is that it just makes a different set of CSS rules apply to the inner price divs. An "ours" within a "theirs" does not display frp, the #pricing.theirs .price.ours rule. A .theirs within a .theirs does display.
I wish the stack snippet showed in reverse the order used — I think this demonstration makes more sense reading the HTML first, then the CSS, and the JS third.
function togglePrices() {
var pricing = document.getElementById('pricing');
pricing.classList.toggle('theirs');
}
document.getElementById('competition')
.addEventListener('change', togglePrices);
#pricing {
margin-top: 1em;
}
#pricing .price.ours,
#pricing.theirs .price.theirs
{
display: block;
}
#pricing .price.theirs,
#pricing.theirs .price.ours
{
display: none;
}
<input type="checkbox" id="competition">
<label for="competition">Competitor's Price</label>
<div id="pricing">
<div class="price ours">
<strong>Our Price</strong><br>
water $1.00<br>
beer $3.00<br>
wine $4.50
</div>
<div class="price theirs">
<strong>Competitors Price</strong><br>
water $1.25<br>
beer $4.00<br>
wine $5.50
</div>
</div>