How to "shrink" repetitive virtually identical javascript/jQuery lines? - javascript

I'm quite new in programming with javascript/jQuery and managed to have the following work but I'm sure there is a way to "shrink" it in a few lines of code. I've tried with each. but didn't manage to work.
What this piece of code does is:
1) You have some divs with "labels" in them.
2) You save a custom title with localStorage through the inputs
3) The titles are updated
Here is jsFiddle for this too
Code:
<div id="theater-1" class="theater">theater 1</div>
<div id="theater-2" class="theater">theater 2</div>
<div id="theater-3" class="theater">theater 3</div>
<div id="theater-4" class="theater">theater 4</div>
<div id="theater-5" class="theater">theater 5</div>
1
<input type="text" id="theater_name_1" class="input-for-theater-title">
<button id="save-title-1">Save</button>
<br> 2
<input type="text" id="theater_name_2" class="input-for-theater-title">
<button id="save-title-2">Save</button>
<br> 3
<input type="text" id="theater_name_3" class="input-for-theater-title">
<button id="save-title-3">Save</button>
<br> 4
<input type="text" id="theater_name_4" class="input-for-theater-title">
<button id="save-title-4">Save</button>
<br> 5
<input type="text" id="theater_name_5" class="input-for-theater-title">
<button id="save-title-5">Save</button>
<button id="clear">Clear</button>
<script>
var theater_1_saved_name = localStorage.getItem("theater_1_name");
var theater_2_saved_name = localStorage.getItem("theater_2_name");
var theater_3_saved_name = localStorage.getItem("theater_3_name");
var theater_4_saved_name = localStorage.getItem("theater_4_name");
var theater_5_saved_name = localStorage.getItem("theater_5_name");
if (theater_1_saved_name !== null) {
document.getElementById("theater-1").innerHTML = theater_1_saved_name;
document.getElementById("theater_name_1").value = theater_1_saved_name;
};
if (theater_2_saved_name !== null) {
document.getElementById("theater-2").innerHTML = theater_2_saved_name;
document.getElementById("theater_name_2").value = theater_2_saved_name;
};
if (theater_3_saved_name !== null) {
document.getElementById("theater-3").innerHTML = theater_3_saved_name;
document.getElementById("theater_name_3").value = theater_3_saved_name;
};
if (theater_4_saved_name !== null) {
document.getElementById("theater-4").innerHTML = theater_4_saved_name;
document.getElementById("theater_name_4").value = theater_4_saved_name;
};
if (theater_5_saved_name !== null) {
document.getElementById("theater-5").innerHTML = theater_5_saved_name;
document.getElementById("theater_name_5").value = theater_5_saved_name;
};
$("#save-title-1").click(function () {
var title_of_1 = $('#theater_name_1').val();
localStorage.setItem("theater_1_name", title_of_1);
$("#theater-1").text(title_of_1);
});
$("#save-title-2").click(function () {
var title_of_2 = $('#theater_name_2').val();
localStorage.setItem("theater_2_name", title_of_2);
$("#theater-2").text(title_of_2);
});
$("#save-title-3").click(function () {
var title_of_3 = $('#theater_name_3').val();
localStorage.setItem("theater_3_name", title_of_3);
$("#theater-3").text(title_of_3);
});
$("#save-title-4").click(function () {
var title_of_4 = $('#theater_name_4').val();
localStorage.setItem("theater_4_name", title_of_4);
$("#theater-4").text(title_of_4);
});
$("#save-title-5").click(function () {
var title_of_5 = $('#theater_name_5').val();
localStorage.setItem("theater_5_name", title_of_5);
$("#theater-5").text(title_of_5);
});
$("#clear").click(function () {
localStorage.clear();
});
</script>

Loops and string concatenation, look for n in the below for the changes:
var n;
for (n = 1; n <= 5; ++n) {
var theater_saved_name = localStorage.getItem("theater_" + n + "_name");
if (theater_saved_name !== null) {
document.getElementById("theater-" + n).innerHTML = theater_saved_name;
document.getElementById("theater_name_" + n).value = theater_saved_name;
}
$("#save-title-" + n).click(function () {
var title = $('#theater_name_' + n).val();
localStorage.setItem("theater_" + n + "_name", title);
$("#theater-" + n).text(title);
});
}
That changes only your JavaScript, not your HTML or the way you store things in local storage. You could change those as well, for instance using a common class for the elements and getting collections of the relevant elements you could index into, but the above is the JavaScript-only change.
Here's an example that changes your HTML (you already mostly had common classes) and local storage; the key is the index argument/variable:
On jsFiddle (Stack Snippets don't support local storage, grrr)
HTML:
<div class="theater">theater 1</div>
<div class="theater">theater 2</div>
<div class="theater">theater 3</div>
<div class="theater">theater 4</div>
<div class="theater">theater 5</div>
1
<input type="text" class="input-for-theater-title">
<button class="save-title">Save</button>
<br>2
<input type="text" class="input-for-theater-title">
<button class="save-title">Save</button>
<br>3
<input type="text" class="input-for-theater-title">
<button class="save-title">Save</button>
<br>4
<input type="text" class="input-for-theater-title">
<button class="save-title">Save</button>
<br>5
<input type="text" class="input-for-theater-title">
<button class="save-title">Save</button>
<button id="clear">Clear</button>
JavaScript:
var theaters = $(".theater");
var inputs = $(".input-for-theater-title");
var buttons = $(".save-title");
theaters.each(function(index) {
var name = localStorage.getItem("theater_" + index + "_name") || "";
$(this).html(name);
inputs.eq(index).val(name);
});
$(document.body).on("click", ".save-title", function() {
var index = buttons.index(this);
var title = inputs.eq(index).val();
localStorage.setItem("theater_" + index + "_name", title);
theaters.eq(index).text(title);
});

Related

I want to use a slider component in html to get input from the user record it and use it to calculate a result

I am using Google App Script. I am trying to connect my HTML doc to my JS doc. So I can get the input from the user and use it to record the info to a Google Sheet and return an on-screen result. I have tried so many things and have come up short.
<div class="card carousel-item">
<div class="card-image">
<img src="https://i.postimg.cc/htb6hMf4/Solution-Builder-Tech-Savvy.png" />
<div class="row">
<div class="range-field">
<div id="min" class="col s1 rangeMinMaxText" style="display: inline">1</div>
<div class="col s10">
<input type="range" id="qt1" min="1" max="5" oninput="updateSliderValue()" />
</div>
<div id="max" class="col s1 rangeMinMaxText" style="display: inline">5</div>
</div>
</div>
<!--CLOSE ROW-->
</div>
<!--CLOSE CARD-->
</div>
document.getElementById("btn").addEventListener("click", doStuff);
function updateSliderValue() {
var sliderValue = document.getElementById("qt1").value;
// document.getElementById("sliderValue").innerHTML = sliderValue;
surveyData.questionOne = sliderValue;
console.log("Slider Value: " + sliderValue);
surveyData = list.map(function (r) {
Logger.log(r[0]);
});
}
function doStuff() {
var qt1 = document.getElementById("qt1");
var qt2 = document.getElementById("qt2");
var qt3 = document.getElementById("qt3");
var qt4 = document.getElementById("qt4");
var qt5 = document.getElementById("qt5");
var qt6 = document.getElementById("qt6");
var qt7 = document.getElementById("qt7");
var qt8 = document.getElementById("qt8");
var qt9 = document.getElementById("qt9");
var qt10 = document.getElementById("qt10");
var qt11 = document.getElementById("qt11");
var qt12 = document.getElementById("qt12");
surveyData.questionOne = qt1.value;
surveyData.questionTwo = qt2.value;
surveyData.questionThree = qt3.value;
surveyData.questionFour = qt4.value;
surveyData.questionFive = qt5.value;
surveyData.questionSix = qt6.value;
surveyData.questionSeven = qt7.value;
surveyData.questionEight = qt8.value;
surveyData.questionNine = qt9.value;
surveyData.questionTen = qt10.value;
surveyData.questionNine = qt11.value;
surveyData.questionTen = qt12.value;
Logger.log(surveyData);
google.script.run.withSuccessHandler(updateResult).userResults(surveyData);
google.script.run.userClicked(surveyData);
function updateResult(result) {
document.getElementById("result").value = result;
M.textareaAutoResize($("result"));
M.updateTextFields("result");
$("result").val("result");
Logger.log(surveyData);
}
}
I tried using all kinds of event listeners. I am able to log the input but having trouble getting it added to an array.
Try something like this.
<input type="range" min="0" max="10" value="0" oninput="rangeOnInput(this)">
<script>
function rangeOnInput(input) {
alert(input.value);
}
</script>

How can I insert elements in an array to a HTML document using Javascript?

I am trying to add the elements of a list called "taskList" made up of values I get from the input elements.
Can anyone please help me, I don't understand why the elements from the list are not showing.
var taskList = [];
var input = document.getElementById('takeInput');
var button = document.getElementById('addInput');
button.onclick = function(){
var nHTML = '';
var userEnteredText = input.value;
taskList.push(userEnteredText);
taskList.forEach(function(task){
nHTML += '<li>'+task+'</li>';
});
document.getElementsByClassName('taskLists').innerHTML = '<ul>' + nHTML + '</ul>';
}
<div class="wrapper">
<header>To-Do List</header>
<div class="taskAdder">
<input id="takeInput" type="text" placeholder="Add your new To-Do">
<button id="addInput" class="button" type="button" >➕</button>
</div>
<div class="taskLists">
</div>
<div class="footer">
<span> You have <span class="pendingTasks"></span> tasks left </span>
<button type="button" class="button">Clear All</button>
</div>
</div>
I tried checking several times but nothing is updating in the HTML document
You shouldn't append to innerHTML, instead, use createElement to make the li, then set innerHTML of that new element to input.value and use appendChild to append it to the list
var input = document.getElementById('takeInput');
var button = document.getElementById('addInput');
var tlist = document.getElementsByClassName('taskLists')[0];
button.onclick = function(){
let e = document.createElement('li');
e.innerHTML = input.value
tlist.appendChild(e)
// Optionally, clear the input field to prevent double adding the same task
input.value = '';
}
<div class="wrapper">
<header>To-Do List</header>
<div class="taskAdder">
<input id="takeInput" type="text" placeholder="Add your new To-Do">
<button id="addInput" class="button" type="button" >➕</button>
</div>
<div class="taskLists">
</div>
<div class="footer">
<span> You have <span class="pendingTasks"></span> tasks left </span>
<button type="button" class="button">Clear All</button>
</div>
</div>
The main mistake was using .getElementsByClassName like it was one element only and not a list (don't ignore the s in elements!).
Anyway I slightly refactored your code to have better strategies for each of its goals and implemented also the logic for clearing the tasks list.
var taskList = [];
var input = document.getElementById('takeInput');
var buttonAdd = document.getElementById('addInput');
var buttonClear = document.getElementById('clearInput');
var tasksList = document.getElementById('tasksList');
buttonAdd.addEventListener('click', (event)=>{
addTask(input.value);
});
buttonClear.addEventListener('click', (event)=>{
tasksList = [];
document.querySelector('#tasksList ul').remove();
});
function addTask(value){
if(taskList.length == 0){
document.getElementById('tasksList').append( document.createElement('ul') );
}
taskList.push(value);
const newLI = document.createElement('li');
newLI.innerText = value;
document.querySelector('#tasksList ul').append(newLI);
}
<body>
<div class="wrapper">
<header>To-Do List</header>
<div class="taskAdder">
<input id="takeInput" type="text" placeholder="Add your new To-Do">
<button id="addInput" class="button" type="button">➕</button>
</div>
<div id="tasksList">
</div>
<div class="footer">
<span> You have <span class="pendingTasks"></span> tasks left </span>
<button id="clearInput" type="button" class="button">Clear All</button>
</div>
</div>
</body>
you just needed to use an ID on the tasklist.
getElementsByClassName needs an index, making your question a dupe of What do querySelectorAll and getElementsBy* methods return?:
document.getElementsByClassName('taskLists')[0].innerHTML
That said, here is a full version using recommended eventListener and IDs where relevant.
let tasks = [];
const taskList = document.getElementById('taskLists')
const input = document.getElementById('takeInput');
const add = document.getElementById('addInput');
const pendingTasks = document.getElementById('pendingTasks');
const clear = document.getElementById('clear');
const showTasks = () => {
taskList.innerHTML = `<ul>${tasks.map(task => `<li>${task}</li>`).join('')}</ul>`;
pendingTasks.textContent = `${tasks.length} task${tasks.length != 1 ? "s" : ""}`;
};
add.addEventListener('click', () => {
var userEnteredText = input.value;
tasks.push(userEnteredText);
showTasks();
});
clear.addEventListener('click', () => {
tasks = [];
showTasks();
});
taskList.addEventListener('click', (e) => {
const tgt = e.target.closest('li');
if (!tgt) return; // not a task
const task = tgt.textContent;
tgt.remove()
tasks = tasks.filter(currentTask => currentTask != task); // remove from list
showTasks()
});
showTasks(); //init
<div class="wrapper">
<header>To-Do List</header>
<div class="taskAdder">
<input id="takeInput" type="text" placeholder="Add your new To-Do">
<button id="addInput" class="button" type="button">➕</button>
</div>
<div id="taskLists"></div>
<div class="footer">
<span> You have <span id="pendingTasks"></span> left </span>
<button type="button" id="clear">Clear All</button>
</div>
</div>

append or remove item from list once toggle is apply active or disactive?

$(document).ready(function() {
var materials = [];
var limit = $("#upper").val();
$("#upper").change(function() {
limit = $(this).val();
});
$(".u").click(function() {
var color = $(this).attr('data-color');
var id = $(this).attr('id');
if (limit > $('.upper :not(.u)').length)
{
$(this).css('background', $(this).attr('data-color'));
var $el = $(this).toggleClass("u");
console.log("added");
} else if (!$(this).hasClass('u')) {
var $el = $(this).toggleClass("u");
console.log("removed");
}
});
});
.u {
background: #FFFFFF!important;
color: #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="upper" type="number" min="1" max="9" class="tbox_style" value="1">
<div class="contents upper">
<div class="u" id="am" data-color="red">Upper Material 1</div>
<div class="u" id="bm" data-color="yellow">Upper Material 2</div>
<div class="u" id="cm" data-color="blue">Upper Material 3</div>
</div>
<div class="hidden">
<input type="hidden" name="u-selected" id="u-selected" value="">
</div>
when upper set to 1 -> log added or removed works okay
Current problem is:
when upper change to 2 or more -> log added or removed work , unexpected ,as below running
My goal is :
when the div is highlight then add into the list.
when the div is not highlight then remove from the list.
You should separate the logic of handling normal case and boundary case (number of not-class-u exceed limit)
$(document).ready(function() {
var materials = []
var limit = $("#upper").val()
$("#upper").change(function() {
limit = $(this).val()
})
$(".u").click(function() {
var color = $(this).attr("data-color")
var id = $(this).attr("id")
var numberOfNotClassU = $(".upper :not(.u)").length
if (limit <= numberOfNotClassU) {
if (!$(this).hasClass("u")) {
var $el = $(this).toggleClass("u")
console.log("removed")
}
return
}
if (!$(this).hasClass("u")) {
var $el = $(this).toggleClass("u")
console.log("removed")
} else {
$(this).css("background", $(this).attr("data-color"))
var $el = $(this).toggleClass("u")
console.log("added")
}
})
})
.u {
background: #FFFFFF!important;
color: #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="upper" type="number" min="1" max="9" class="tbox_style" value="1">
<div class="contents upper">
<div class="u" id="am" data-color="red">Upper Material 1</div>
<div class="u" id="bm" data-color="yellow">Upper Material 2</div>
<div class="u" id="cm" data-color="blue">Upper Material 3</div>
</div>
<div class="hidden">
<input type="hidden" name="u-selected" id="u-selected" value="">
</div>

What will be the Javascript code for this for changing the ID of each tag while making a clone every time?

I want to clone the template and show it to the <div id= "wrapper"> with different ID every time I make a clone. When I press the add-new-project button a new template is shown with different "ID" every time.
Javascript code:
$("document").ready(function () {
var cloneCntr = 1;
var i = 0;
$("#projectData").on('click', function () {
$('template').children().each(function () {
this.id = this.id+ this.i;
});
var temp = document.getElementsByTagName("template")[0];
var clon = temp.content.cloneNode(true);
i++;
$('#wrapper').append(clon);
});
});
Html code:
<form id="projectForm">
<div class="container">
////// ---------------------code-------//// <br>
<br>
<h4>Project Experience</h4>
<hr>
<template id="template">
<br>
<br>
<div class="form-row">
---------Template Code-------
</div>
</div>
<hr>
</template>
</div>
<div id="wrapper" class="container">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<div class="container">
<button type="button" id="projectData" class="btn btn-primary">Add New Project</button>
</div>
</body>
</html>
I want to replace every tag "id" in the template, every time when I make a clone of this.
Here's an example of how this could work for you.
See a demo here: https://jsfiddle.net/o76pqxyw/
Here's a screenshare, showing how the IDs change: https://www.loom.com/share/4a1556c4bb5c4422ad1d4b20a12a638a
HTML
<div id="template-form">
<p><label>First Name</label> <input type="text" id="first-name" /></p>
<p><label>Last Name</label> <input type="text" id="last-name" /></p>
</div>
<button id="btn">Add New User</button>
<div id="container"></div>
Javascript
const button = $('#btn');
const target = $('#container');
let counter = 0;
$(button).on('click', () => {
const template = $('#template-form');
const copy = $(template).clone();
counter++;
const elements = $(copy).find('input');
$(elements).each(function(index) {
const currentId = $(this).attr('id');
const newId = currentId + '-' + counter;
$(this).attr('id', newId);
});
$(target).append(copy);
})

Javascript based game

So i've been trying make a game where you bet money and if you win you get a profit, to win you must guess the correct outcome of the dice (6 sided) if you do you get your money + profit, i have been kind of successful but it dosen't pay you.
if you could help me fix this thanks. WEBSITE: http://csgodice.net16.net/dice.php
EDIT : Added the whole code!
EDIT: Things still broken with a new error: game is not defined.
CSGODice.net
<div id="header">
<div id="navbar">
<a class="nav1" href="/"><bold>HOME</bold></a>
<a class="nav2" href="dice.php"><bold>DICE</bold></a>
<a class="nav3" href="support.php">SUPPORT</a>
<a class="balance" href="#">Gems: 0</a>
<div id="steamLogon">
<?php
require 'steamauth/steamauth.php';
if(!isset($_SESSION['steamid'])) {
loginbutton("small"); //login button
} else {
include ('steamauth/userInfo.php'); //To access the $steamprofile array
//Protected content
logoutbutton(); //Logout Button
}
?>
</div>
</div>
<div id="dicelogo">
<a href="/">
<img src="img/logo.png" alt="logo" id="logo"/>
</a>
</div>
</div>
<div id="dicegame">
<div id="diceholder">
<h1>
<div id="diceroller">
<span id="value" class="lable_value">0</span>
<script>
var m = document.getElementsByClassName("balance");
var o = document.getElementsById("diceroller");
var w = document.getElementsByClassName("winchance");
var uc = document.getElementsByClassName("userchoice").value;
var b = document.getElementsById("bet").value;
var p = document.getElementsById("profit");
function game(event){
var wn = Math.floor((Math.random() * 6) + 1);
o.innerText = wn;
if(uc.value == wn) {
m.innerText = m.innerText + profit.innerText + b;
} else {
m.innerText = m.innerText - b;
}
}
</script>
</div>
</h1>
<h3>
<div class="winchance">1 - 6</div>
</h3>
</div>
<div id="inputholder">
<div id="input">
<div class="betamount">
<b>Gems to bet:</b>
</div>
<form class="input-money">
<b><input id="bet" oninput="edValueKeyPress()" type="number" name="bet" style="color: #404040;" class="form-control" min="0.10" step="any" max="1000.00" value="1.00"></b>
</form>
<div class="profitamount">
<b>Profit:</b>
</div>
<div id="profit">
</div>
<div id="userchoicetext"><b>Prediction:</b></div>
<form>
<input id="userchoice" oninput="edValueKeyPress()" type="number" name="choice" style="color: #404040" class="form-choice" min="1" step="any" max="6" value="1"/>
</form>
<button id="playgame" onclick="game()">Throw!</button>
</div>
</div>
</div>
<script>
var input = document.getElementsByClassName("form-control");
function edValueKeyPress(event)
{
var input = document.getElementById("bet").value;
var x = document.getElementById("profit"); // Find the elements
x.innerText= input * 0.68; // Change the content
var n = event.toFixed(2);
}
</script>
</div>
</div>
</div>
You have several errors here:
First a simple typo:
You define a variable here
var b = document.getElementsById("bet").value;
an try to access it as bet
m.innerText = m.innerText + profit.innerText + bet;
Next misstake:
getElementsById must be getElementById
next:
getElementsByClassName returns an array of Nodes, not only the first node it finds, so var uc = document.getElementsByClassName("userchoice").value; is an error.
Your debugged code:
var m = document.getElementsByClassName("balance")[0];
var o = document.getElementById("diceroller");
var w = document.getElementsByClassName("winchance")[0];
var uc = document.getElementsByClassName("userchoice")[0].value;
var bet = document.getElementById("bet").value;
var p = document.getElementById("profit");
function game(event){
var wn = Math.floor((Math.random() * 6) + 1);
o.innerText = wn;
if(uc.value == wn) {
m.innerText = m.innerText + profit.innerText + bet;
} else {
m.innerText = m.innerText - b;
}
}
I'd highly recommend to give those specific elements an ID and find them via that, rather than a classname.
All these errors are shown in the console - one after each other. Use that to debug your code yourself in the future!

Categories