I'm working on a portfolio project - which should use jquery - part of the task is to set and get text via localstorage - which I can do in Javascript but I breaks when attempting to refactor in jquery.
I found an elegantly simple javascript codepen, which has all the features I want. But when I refactor into jquery it loses funtionality - I can't save the text to local storage (I get null) and I can't copy the text to a different Div.
This is the HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Local Test</title>
</head>
<body>
<div class="content-output"></div>
<textarea class="content-input" placeholder="Your text here"></textarea>
<button class="save-button">Save</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="./script.js"></script>
</body>
</html>
This is simple CSS from the JS code pen:
* {
font-size: 16px;
font-family: sans-serif;
}
body {
padding: 1rem;
font-family: sans-serif;
}
.content-output {
float: left;
box-sizing: border-box;
background: #f9f9f9;
padding: 0.5rem;
width: calc(50% - 1rem);
height: 10rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
color: #202020;
}
.content-input {
float: left;
box-sizing: border-box;
margin-left: 2rem;
padding: 0.5rem;
width: calc(50% - 1rem);
height: 10rem;
border: 1px solid #505050;
resize: none;
}
.save-button {
/* -webkit-appearance: none; */
border: 0;
background: #0088ff;
padding: 0.5rem 1rem;
border-radius: 3px;
color: #fff;
margin-top: 1rem;
float: right;
cursor: pointer;
}
Here is the JS which works:
var input_textarea = document.querySelector(".content-input");
var output_div = document.querySelector(".content-output");
var save_button = document.querySelector(".save-button");
save_button.addEventListener("click", updateOutput);
output = localStorage.getItem("content");
input = localStorage.getItem("content");
console.log(output);
output_div.textContent = output;
function updateOutput() {
console.log("clicked button");
localStorage.setItem("content", input_textarea.value);
output_div.textContent = input_textarea.value;
}
And here is the jquery which doesn't work:
var input_textarea = $(".content-input");
var output_div = $(".content-output");
var save_button = $(".save-button");
save_button.on("click", updateOutput);
output_div.textContent = localStorage.getItem("content");
input_textarea.value = localStorage.getItem(("content"));
function updateOutput(event) {
event.preventDefault();
localStorage.setItem("content", input_textarea.value);
output_div.textContent = input_textarea.value;
}
I'm running out of ideas and searches - probably a typo but I cant find it . I've tried text() which was the advice 6 years ago. JSON.stringify and parse don't help because it's just a string.
I'm hoping someone has done some refactoring and spots the differences - I've even run this in the console but I can only add the text to localstorage manually: localstorage.setItem('content', 'help')
Thanks in advance
The problem is that you are trying to select a array, get the value of that array, and output to another array. I think jquery does that when you select a class, (because there could be more than one of them). Simple solution to this..
var input_textarea = $(".content-input")[0];
console.log(input_textarea)
var output_div = $(".content-output")[0];
var save_button = $(".save-button");
save_button.on("click", updateOutput);
output_div.textContent = localStorage.getItem("content");
input_textarea.value = localStorage.getItem(("content"));
function updateOutput(event) {
console.log('hello')
event.preventDefault();
localStorage.setItem("content", input_textarea.value);
output_div.textContent = input_textarea.value;
}
Found it: val() to set and text() to get.
var input_textarea = $(".content-input");
var output_div = $(".content-output");
var save_button = $(".save-button");
save_button.on("click", updateOutput);
// input_textarea.value = localStorage.getItem(("content"));
function updateOutput(event) {
event.preventDefault();
localStorage.setItem("content", input_textarea.val());
output_div.text(localStorage.getItem("content"));
}
this post helped: How to save the value of textarea to localstorage then display it in the same textarea
Related
I'm running my code in node.js I've seen that running code in node could play a part. But this was never a problem. It keeps saying my variable that points to my element 'document is not defined'. I don't know what I'm doing wrong, I'm linking it correctly but still confused I also tried putting my scripts on the bottom and top with defer.
let seconds = 00;
let tens = 00;
let appendTens = document.querySelector('#tens');
let appendSeconds = document.querySelector('#seconds');
let stop = document.querySelector('#button-stop');
let start = document.querySelector('#button-start');
let reset = document.querySelector('#button-reset');
let interval; //store timer values
// this function will run when start is clicked
const startTimer = () =>{
tens++
if(tens < 9){
appendTens.textContent = `0${tens}`
}
if(tens > 9){
appendTens.textContent = tens;
}
if(tens > 99){
seconds++
appendSeconds.textContent = `0${seconds}`;
tens = 0;
appendTens.textContent = "0" + 0;
}
if(seconds > 9){
appendSeconds.textContent = seconds;
}
};
start.onclick = function(){
interval = setinterval(startTimer)
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stopwatch</title>
<link rel="stylesheet" href="stopwatch.css">
</head>
<body>
<div class="wrapper">
<h1>Stopwatch</h1>
<h2>Vanilla JavaScript Stopwatch</h2>
<p><span id="seconds">00</span>:<span id="tens">00</span></p>
<button id="button-start">Start</button>
<button id="button-stop">Stop</button>
<button id="button-reset">Reset</button>
</div>
<script type="module" src="stopwatcj.js"></script>
</body>
</html>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-self: center;
background-color: rgb(248, 180, 55);
}
.wrapper {
margin-top: 10%;
text-align: center;
color: #fff;
}
.wrapper button {
background-color: rgb(248, 180, 55);
border: 1px solid white;
padding: 10px 20px;
color: #fff;
}
.wrapper button:hover {
cursor: pointer;
opacity: 30%;
}
document which is a part of Html DOM is not a part of nodejs. Since you might be using nodejs to compile your js code that's why you are getting this error. Please try to run this simply in browser.
I am trying to build a static todo app, this app stores the todo list in localStorage (browser memory).
there are 3 elements related to the error - 1 element is causing the error and the other 2 being affected by it.
a hide complete checkbox - hides the completed tasks when checked. (element causing the error)
complete todo checkbox - mark a todo as completed when checked.
delete note button - deletes a note.
I have attached the code files and screenshot, to get an overall idea about the problem and the code.
along with this, I have stored my code in this repo: https://github.com/AbhishekTomr/Todo
Problem - Once the hide completed checkbox is triggered, the complete todo and delete todo mechanism stops working.
Can someone please help me in fixing the code or let me know what is causing the issue?
Screenshot:
//js file : todoFunctions.js
//function for getting value stored in todoList
let getTodo = function(){
return Boolean(localStorage.getItem("todo"))?JSON.parse(localStorage.getItem("todo")):[];
}
//function to add or render any list on the screen
let render = function(list){
document.querySelector("#td").innerHTML = "";
list.forEach(function(item){
newTask(item);
}
)
}
//function for saving the task in the local storage
let saveTask = function(todo){
let tdList = JSON.stringify(todo);
localStorage.setItem("todo",tdList); //setting value for the first time or updating it
}
let newTask = function(node)
{
let li = document.createElement("li");
let status = document.createElement("input");
let remove = document.createElement("button");
li.textContent = node.td;
remove.setAttribute("class","remove");
remove.textContent="Delete";
status.setAttribute("type","checkbox");
status.setAttribute("class","status");
status.checked = node.status;
li.style.textDecoration = (node.status)?"line-through":"none";
let div = document.createElement("div");
div.setAttribute("class","task");
div.setAttribute("id",node.index);
div.appendChild(status);
div.appendChild(li);
div.appendChild(remove);
document.querySelector("#td").appendChild(div);
document.getElementById("new-task").value = ""; //clearing the input feild
}
//function for adding a new task
let addTask = function(todo){
let td = document.getElementById("new-task").value;
let status = false;
let node = {td : td,status : status};
todo.push(node);
saveTask(todo); // saving it to local storage
newTask(node);
}
// function for searching out task
let searchTask = function(todo,e){
let searchList = todo.filter(function(item){
return item.td.includes(e.target.value);
})
render(searchList); // showing the searched terms on the go..
}
//funtion to delete task
let deleteTodo=function(e,index,todo){
e.target.parentElement.remove();
todo.splice(index,1);
saveTask(todo);
}
//funtion for completing and undoing a task
let changeStatus = function(e,index,todo){
let state = e.target.checked;
let td = e.target.parentElement.children[1];
td.style.textDecoration = (state)?"line-through":"none";
todo[index].status = state;
saveTask(todo);
}
//function for hiding complete task
let hideCompleted = function(e,todo){
if(e.target.checked)
{
let filterLst = todo.filter(function(item){
return !item.status;
})
render(filterLst);
}else{
render(todo);
}
}
//js file :main.js
let todo = getTodo(); // get the todo List from storage
render(todo); // display the initial todo List
//functionality for the different events
document.getElementById("add-task").addEventListener("click",function(e){ //event when the add new task button is pressed
addTask(todo); //funtion for adding new task and displaying it on page
})
document.getElementById("search-txt").addEventListener("input",function(e){ //event for text typed in seach bar
searchTask(todo,e); //funtion for searching the tasks and displaying it on page
})
//event to delete todo
let btns = document.querySelectorAll(".remove");
btns.forEach(function(item,index){
item.addEventListener("click",function(e){
deleteTodo(e,index,todo);
})
})
//event for complete/uncomplete task
let check = document.querySelectorAll(".status");
check.forEach(function(item,index){
item.addEventListener("change",function(e){
changeStatus(e,index,todo);
console.log("i am triggered");
})
})
document.querySelector("#hide-check").addEventListener("change",function(e){ //event when hide completed is checked and unchecked
hideCompleted(e,todo);
})
/* css file : main.css */
*{
margin: 0;
padding: 0;
box-sizing: border-box;
/* border: 1px solid black; */
font-family: monospace;
}
main{
margin: 5px;
}
h1{
font-size: 3rem;
font-weight: bold;
font-variant: small-caps;
display: inline-block;
width: 250px;
text-align: center;
}
#td-options{
display: flex;
flex-flow: column nowrap;
justify-content:space-around;
align-items: flex-start;
font-size: 1.2rem;
width: 250px;
}
#search,#search input{
width: 100%;
height: 100%;
text-align: center;
border: 2px solid black;
}
#hide-completed{
width: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
font-size: 1.2rem;
margin: 5px 0;
}
#hide-check{
margin: 10px;
}
#todo{
/* border: 3px solid pink; */
background-color: pink;
margin: 1rem 0;
display: inline-block;
padding: 10px;
}
.task{
border: 1px solid green;
display: flex;
justify-content: flex-start;
align-items: center;
font-size: 1.2rem;
}
.task li{
list-style-position: inside;
margin: .5rem;
text-transform: capitalize;
}
.task button{
padding: 0 .5rem;
border-radius: 2px;
background-color: gray;
color: whitesmoke;
}
.task button:hover{
cursor: pointer;
}
#add-todo{
display: flex;
flex-flow: row nowrap;
width: 255px;
justify-content: space-between;
height: 25px;
}
#add-todo button{
padding: 0 .5rem;
border-radius: 3px;
}
<!-- html file: index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="main.css">
<title>Todo</title>
</head>
<body>
<main>
<!-- mainheading -->
<h1>My Todo App</h1>
<!--todoOptions-->
<div id="td-options">
<div id="search">
<input type="text" id="search-txt" placeholder="search your Todo">
</div>
<div id="hide-completed">
<label for="hide-check">
Hide Completed Tasks
</label>
<input type="checkbox" id="hide-check" name="hide">
</div>
</div>
<!-- todo list -->
<div id="todo">
<ol id="td"></ol>
</div>
<!-- add todo -->
<div id="add-todo">
<input type="text" placeholder="Add A New To Do Task" id="new-task">
<button id="add-task">Add ToDo</button>
</div>
<!-- js files -->
<script src="todoFunctions.js"></script>
<script src="main.js"></script>
</main>
</body>
</html>
The function render goes through a list and creates the relevant elements for a task to show it on the screen and then appends them.
At the start a list is collected from localstorage and then all the required event listeners are added.
When hideCompleted is called it creates a list from the remaining elements that are not completed, or just uses the complete todo list, and re-renders it. This creates all the elements OK so everything looks alright on the screen.
BUT no event listeners are added so the delete button and so on do not do anything.
My suggestion would be to make the event listener creation code for .remove etc into a function. Call that on start up and when you recreate the list on screen.
I have written this code to get the squares of a grid to change their background color to black upon a mouseover event. It works when the page initially loads, but if I create a new grid the mouseover event no longer works.
I updated the original post with a snippet. Sorry I didn't do that from the beginning.
let number = 16;
makeGrid(number);
function makeGrid(number) {
for (let i=0; i < number; i++) {
for (let j=0; j < number; j++) {
const rows = document.createElement('div');
const container = document.getElementById('container')
rows.setAttribute('class', 'rows');
container.appendChild(rows);
}
}
container.style.gridTemplateColumns = `repeat(${number}, 1fr)`;
container.style.gridTemplateRows = `repeat(${number}, 1fr)`;
}
//create new grid with on button
let newGrid = document.getElementById('newGrid');
newGrid.addEventListener('click', () => {
let number = prompt('Enter a number');
let container = document.getElementById('container');
container.textContent = '';
makeGrid(number);
})
//change background color to black
let changeClass = document.querySelectorAll('.rows');
changeClass.forEach((item) => {
item.addEventListener('mouseover', e => {
item.style.backgroundColor = 'black';
})
})
body {
background-color: rgb(5, 51, 5) ;
}
#container {
margin: auto;
width: 500px;
height: 500px;
display: grid;
border-style: solid;
border-width: thin;
border-color: lightslategray;
background-color: white;
}
.rows{
}
.black { background-color: black;
}
#header {
text-align: center;
}
#button {
text-align: center;
}
#footer {
text-align: center;
}
#newGrid {
background-color: lightgray;
color: darkcyan;
font-size: 20px;
padding: 12px 28px;
border-radius: 0px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Etch-a-Sketch</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1 id='header'>Etch-a-Sketch</h1>
<br>
<div id='button'>
<button id='newGrid' class='button'>New Grid</button>
</div>
<br>
<br>
<div id='container'></div>
<br>
<footer id='footer'>Made by: Joe Maniaci</footer>
<script src="main.js"></script>
</body>
</html>
When you query the DOM with document.querySelectorAll('.rows') and add the event listeners, there is only one "grid" in the DOM at that time. When a "grid" is subsequently added to the DOM, as triggered by the user's click event, you must instantiate event listeners on the newly added DOM nodes too.
A way to avoid this problem and a better approach overall in your situation is to use delegated event listeners. For example:
document.addEventListener('mouseover', e=>{
if(e.target.matches(‘.myClickableItemClass’){
e.target.style.backgroundColor = 'black';
}
}
Learn more about event delegation here: https://medium.com/#bretdoucette/part-4-what-is-event-delegation-in-javascript-f5c8c0de2983
can someone take a look at this and tell me what I'm doing wrong?
I wanted to use these other techniques just as an exercise.
such as using element id / using a separate js file to recreate a clock application that shows the current date. However, it keeps showing up as blank:
"use strict";
var $ = function(id) { return document.getElementById(id); };
var padSingleDigit = function(num) {
return (num < 10) ? "0" + num : num;
};
// callback function for displaying clock time
var displayTime = function(now) {
$("hours").firstChild.nodeValue = now.hours;
$("minutes").firstChild.nodeValue = padSingleDigit(now.minutes);
$("seconds").firstChild.nodeValue = padSingleDigit(now.seconds);
$("ampm").firstChild.nodeValue = now.ampm;
// display date in "m/d/yyyy" format - correct for zero-based month
var date = (now.getMonth() + 1) + "/" + now.getDate() + "/" + now.getFullYear();
$("date").firstChild.nodeValue = date;
};
// onload event handler
window.onload = function() {
var clock = createClock(displayTime);
// start clock
clock.start();
};
body {
font-family: Arial, Helvetica, sans-serif;
background-color: white;
margin: 0 auto;
width: 450px;
border: 3px solid blue;
padding: 0 2em 1em;
}
h1 {
color: blue;
}
label {
float: left;
width: 11em;
text-align: right;
padding-bottom: .5em;
}
input {
margin-left: 1em;
margin-bottom: .5em;
}
fieldset {
margin-bottom: 1em;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Clock</title>
<link rel="stylesheet" href="clock.css">
<script src="clock.js"></script>
</head>
<body>
<main>
<h1>Digital clock</h1>
<fieldset>
<legend>Clock</legend>
<span id="date"> </span>:
<span id="minutes"> </span>:
<span id="seconds"> </span>
<span id="ampm"> </span>
</fieldset>
</main>
</body>
</html>
The problem is you are referencing an element that does not exist. There is no element with the id of "hours" in your code.
<script>
$(document).ready(function(){
// Function to get the Max value in Array
Array.max = function( array ){
return Math.max.apply( Math, array );
};
//select row on which conditional formatting will apply
$(".conditional").each(function(){
// get all TDs except for first column
var counts= $(this).find(':nth-child(n+1)');
// return max value
var max = Array.max(counts);
xr = 255;
xg = 255;
xb = 255;
yr = 243;
yg = 32;
yb = 117;
n = 100;
// Iterates on each TD except the first column
$(this).find(':nth-child(n+1)').each(function(){
//assign color based on difference from min and max
var val = parseInt($(this).text());
var pos = parseInt((Math.round((val/max)*100)).toFixed(0));
red = parseInt((xr + (( pos * (yr - xr)) / (n-1))).toFixed(0));
green = parseInt((xg + (( pos * (yg - xg)) / (n-1))).toFixed(0));
blue = parseInt((xb + (( pos * (yb - xb)) / (n-1))).toFixed(0));
clr = 'rgb('+red+','+green+','+blue+')';
$(this).css("background-color",clr);
});
});
});
</script>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<style type="text/css">
.year {
background-color: #eeeeee;
font-size: 30px;
text-align: center;
font-weight: bold;
padding: 30px;
}
table.tableizer-table {
border: 1px solid #CCC; font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
margin:auto
}
.tableizer-table td {
padding: 10px;
margin: 5px;
border: 1px solid #ccc;
text-align: center;
width:120px;
}
.tableizer-table th {
background-color: #eeeeee;
color: #111;
font-weight: bold;
padding: 10px;
font-size: 18px;
}
.separator {
background-color: #ffffff;
}
.firstcolumn {
font-weight: bold;
}
</style>
</head>
<body>
<table id="mytable" class="tableizer-table">
<tr><td class="year">2015</td></tr>
<tr class="conditional"><td class="firstcolumn">Hwy (MPGe)</td><td>109</td><td>108</td><td>110</td><td>92</td><td>101</td><td>93</td><td> </td></tr>
<tr class="conditional"><td class="firstcolumn">City (MPGe)</td><td>128</td><td>122</td><td>99</td><td>120</td><td>126</td><td>122</td><td> </td></tr>
<tr class="conditional"><td class="firstcolumn">Combined (MPGe)</td><td>119</td><td> </td><td>105</td><td>105</td><td>114</td><td>114</td><td> </td></tr>
</table>
I am new to Jquery and javascript and trying to implement conditional formatting on a html table. Where the numbers in one row are compared and the lowest element will have a white background and the highest number will have a green background.
The rows on which the conditional formatting needs to work have a class called "conditional". The first column does not contain a number so needs to be excluded from the conditional formatting.
I have been spending several days to do this and cannot succeed.
I found the following piece of code and modified it slightly for my specific needs but it does not work.
I ran it in a browser called from this HTML document:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script src='~/altitude/jquery-2.1.4.min.js'></script>
<script type="text/javascript" src="~/workspace/test.js";></script>
</head>
<body>
<ul id = "squarePos">
<li class = "conditional">Header</div>
<li class = "conditional">1</div>
<li class = "conditional">4</div>
<li class = "conditional">2</div>
<li class = "conditional">3</div>
</ul>
</body>
</html>
The code won't run because you seem to have more than one set of unmatching parenthesis or brackets.
If you use firefox (which I do for web developement) you can hit Ctrl-Shift-K to get a web console that will show you where you have syntax errors in your javascript so you can get on to the debugging.