Using multiple checkboxes, all made by a javascript function, with Javascript - javascript

A function uses Google Maps API results to create a list of places (hotels etc.) besides each one there is a checkbox:
if(place['rating']) {
LocationName = place['name'];
LocationString += `<div class="input-group" id="Location-checkbox-${[i]}">
<span value=${[i]} class="input-group-addon">
<input type="checkbox" name="choice"
id="checkboxes" aria-label="..." onclick="chooseSelection(${[i]})">
</span>
<li id="Location-${[i]}" class="list-group-
item"><strong id="locationName-${[i]}">${LocationName}</strong><br>`;
if(place['rating']) {
var LocationRating = place['rating'];
LocationString += `rating: <span
id="locationRating-${[i]}">${LocationRating}</span><br>`;
} else {
var LocationRating = 'This place has no rating';
LocationString += LocationRating;
}
if(place['user_ratings_total']) {
var LocationUsers = place['user_ratings_total'];
LocationString += `based on ${LocationUsers} reviews</li></div>`;
} else {
var LocationUsers = '</li></div>';
LocationString += LocationUsers;
}
htmlString += LocationString;
I then need to add the ones the user chooses into an temporary array:
var temporarySelection = "";
var placeSelection = "";
var hotelSelection = "";
var restaurantSelections = "";
var sightSelections = "";
function chooseSelection(resultIndex) {
var locationName = document.getElementById('locationName-' + resultIndex);
temporarySelection += `<div class="input-group" id="Hotel-chosen">
<li class="list-group-item">
<strong>${locationName.innerHTML}</strong><br>`;
var locationRating = document.getElementById('locationRating-' +
resultIndex);
temporarySelection += `rating: ${locationRating.innerHTML}</li></div>`
}
Lastly, I need to move the temporary selection into ANOTHER array.
My problem is that, at the moment, the checkboxes are just working like buttons. Every time you click it, it just adds another one to the array. I want to only add the ones to the array that are ticked when the Next button is clicked (not shown in the code).
Any advice?

Related

JavaScript arrays adding last element instead of recently added input

Good evening. I am new to JavaScript and I need help with my mini-project and I have only one issue here and it is in the this.Add = function ().
It works properly when I enter a duplicate value from my list therefore it displays an alert that no dupes are allowed. But... when I enter a unique value, it only adds up the last element present (Wash the dishes) from myTasks list. instead of the one I recently entered and the list goes on adding the same ones. Did I just misplace something?
This is my final activity yet and I want to finish it to move to the next function. Thank you in advance.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tasks CRUD</title>
<style>
#tasks{
display: none;
}
</style>
</head>
<body>
<center>
<form action="javascript:void(0);" method="POST" onsubmit="app.Add()">
<input type="text" id="add-task" placeholder="Add another card">
<input type="submit" value="Add">
</form>
<div id="tasks" role="aria-hidden">
<form action="javascript:void(0);" method="POST" id="saveEdit">
<input type="text" id="edit-task">
<input type="submit" value="Edit" /> <a onclick="CloseInput()" aria-label="Close">✖</a>
</form>
</div>
<p id="counter"></p>
<table>
<tr>
<th>Name</th>
</tr>
<tbody id="myTasks">
</tbody>
</table>
</center>
<script>
var app = new function() {
this.el = document.getElementById('myTasks');
this.myTasks = ['Clean the bathroom', 'Wash the dishes'];
this.Count = function(data) {
var el = document.getElementById('counter');
var name = 'task';
if (data) {
if (data > 1) {
name = 'Things To DO';
}
el.innerHTML = data + ' ' + name ;
} else {
el.innerHTML = 'No ' + name;
}
};
this.FetchAll = function() {
var data = '';
if (this.myTasks.length > 0) {
for (i = 0; i < this.myTasks.length; i++) {
data += '<tr>';
data += '<td>' + this.myTasks[i] + '</td>';
data += '<td><button onclick="app.Edit(' + i + ')">Edit</button></td>';
data += '<td><button onclick="app.Delete(' + i + ')">Delete</button></td>';
data += '</tr>';
}
}
this.Count(this.myTasks.length);
return this.el.innerHTML = data;
};
this.Add = function () {
el = document.getElementById('add-task');
// Get the value
var task = el.value;
if (task ) {
for(task of this.myTasks)
{
var ctr = 0;
if(document.getElementById("add-task").value == task){
ctr = 1;
break;
}
}
if(ctr == 1)
{
window.alert("Duplicates not allowed.");
}else{
// Add the new value
this.myTasks.push(task.trim());
// Reset input value
el.value = '';
// Dislay the new list
this.FetchAll();
}
}
};
this.Edit = function (item) {
var el = document.getElementById('edit-task');
// Display value in the field
el.value = this.myTasks[item];
// Display fields
document.getElementById('tasks').style.display = 'block';
self = this;
document.getElementById('saveEdit').onsubmit = function() {
// Get value
var task = el.value;
if (task) {
// Edit value
self.myTasks.splice(item, 1, task.trim());
// Display the new list
self.FetchAll();
// Hide fields
CloseInput();
}
}
};
this.Delete = function (item) {
// Delete the current row
this.myTasks.splice(item, 1);
// Display the new list
this.FetchAll();
};
}
app.FetchAll();
function CloseInput() {
document.getElementById('tasks').style.display = 'none';
}
</script>
</body>
</html>
In your for loop:
for (task of this.myTask) {
}
You are not declaring a new task variable, but instead assigning to the outer task variable, hence the repeated addition of tasks already in your list.
You can declare a new variable in the for scope like so:
for (const task of this.myTask) {
}
Your HTML as it is.
And your Javascript goes like below. You have a bug while checking if the task already exists in the array. As you're comparing string value either use simple for loop with triple equals or do as i have attached below.
var app = new function() {
this.el = document.getElementById('myTasks');
this.myTasks = ['Clean the bathroom', 'Wash the dishes'];
this.Count = function(data) {
var el = document.getElementById('counter');
var name = 'task';
if (data) {
if (data > 1) {
name = 'Things To DO';
}
el.innerHTML = data + ' ' + name ;
} else {
el.innerHTML = 'No ' + name;
}
};
this.FetchAll = function() {
var data = '';
if (this.myTasks.length > 0) {
for (i = 0; i < this.myTasks.length; i++) {
data += '<tr>';
data += '<td>' + this.myTasks[i] + '</td>';
data += '<td><button onclick="app.Edit(' + i + ')">Edit</button></td>';
data += '<td><button onclick="app.Delete(' + i + ')">Delete</button></td>';
data += '</tr>';
}
}
this.Count(this.myTasks.length);
console.log(this.myTasks.length);
return this.el.innerHTML = data;
};
this.Add = function () {
el = document.getElementById('add-task');
// Get the value
var task = el.value;
console.log(task);
if (task ){
var arrayContainsTask = (this.myTasks.indexOf(task) > -1);
if(arrayContainsTask == true){
window.alert("Duplicates not allowed.");
}else{
// Add the new value
this.myTasks.push(task);
// Reset input value
el.value = '';
}
// Dislay the new list
this.FetchAll();
}
}
}

Loop through div children and bold specific text not working

I have a suggestion dropdown under an input field and I am trying to make the text in the suggestion divs bold for the portion that matches what is currently in the input field.
e.g
input: AB
dropdown: ABCDE
My current code doesn't seem to be replacing the div content with the span
JS:
BoldMatchedText(inputToMatch:string){
var outerDiv = document.getElementById("dropdown");
if(outerDiv != null){
var subDiv = outerDiv.getElementsByTagName("div");
for (var i = 0; i < subDiv.length; i++){
subDiv[i].innerHTML.replace(inputToMatch, "<span id=\"strong\">" + inputToMatch + "</span>");
}
}
}
html:
<form>
<input type="text" id="dropdown-input">
<div id="dropdown">
<div class="reg-list-item">{{reg1}}</div>
<div class="reg-list-item">{{reg2}}</div>
<div class="reg-list-item">{{reg3}}</div>
<div class="reg-list-item">{{reg4}}</div>
</div>
</form>
You need to assign the result of calling the function replace.
subDiv[i].innerHTML = subDiv[i].innerHTML.replace(inputToMatch, "<span id=\"strong\">" + inputToMatch + "</span>");
function BoldMatchedText(inputToMatch) {
var outerDiv = document.getElementById("dropdown");
if (outerDiv != null) {
var subDiv = outerDiv.getElementsByTagName("div");
for (var i = 0; i < subDiv.length; i++) {
subDiv[i].innerHTML = subDiv[i].innerHTML.replace(inputToMatch, "<span id=\"strong\">" + inputToMatch + "</span>");
}
}
}
BoldMatchedText('Go');
#strong {
font-weight: 700
}
<form>
<input type="text" id="dropdown-input">
<div id="dropdown">
<div class="reg-list-item">Ele</div>
<div class="reg-list-item">Gomez</div>
<div class="reg-list-item">Rod</div>
<div class="reg-list-item">Enr</div>
</div>
</form>
Try this working sample with a benchmark. Compared with the previous answer.
function BoldMatchedText1(inputToMatch) {
var outerDiv = document.getElementById("dropdown");
if (outerDiv != null) {
var subDiv = outerDiv.getElementsByTagName("div");
for (var i = 0; i < subDiv.length; i++) {
subDiv[i].innerHTML = subDiv[i].innerHTML.replace(inputToMatch, "<span id=\"strong\">" + inputToMatch + "</span>");
}
}
}
function BoldMatchedText2(inputToMatch) {
var outerDiv = document.getElementById("dropdown");
if(outerDiv !== null) {
// Use `getElementsByClassName` instead using `getElementsByTagName('div')` JS will traverse your entire HTML file and look for all div tags, may take a little longer if you have a lot
var items = outerDiv.getElementsByClassName("reg-list-item");
// Getting the iteration length before the loop will give you performance benefit since items.length will not be checked per iteration
var len = items.length;
// Using while loop evaluating only if len is any positive number (true) except 0 (false) with reverse iteration making it faster
while(len--) {
var item = items[len].innerHTML;
// ONLY replace the text that contains the `inputToMatch`
if(item.indexOf(inputToMatch) !== -1) {
items[len].innerHTML = item.replace(inputToMatch, "<span id=\"strong\">" + inputToMatch + "</span>");
}
}
}
}
console.time('filter1');
BoldMatchedText1('Gom');
console.timeEnd('filter1');
console.time('filter2');
BoldMatchedText2('Gom');
console.timeEnd('filter2');
#strong {
font-weight: 700
}
<form>
<input type="text" id="dropdown-input">
<div id="dropdown">
<div class="reg-list-item">Ele</div>
<div class="reg-list-item">Gomez</div>
<div class="reg-list-item">Rod</div>
<div class="reg-list-item">Enr</div>
</div>
</form>

How to create a <ul> based on an array number

I am trying to make a GitHub profile searcher and what i'm trying to do is:
Get the user Avatar
Get the user Name
Get the user Repositories
I'm having troubles with the last one.
What i can't figure out is how to create a UL based in the user repos quantity.
What i have HTML:
<!DOCTYPE html>
<html>
<head>
<title>Github Profile Searcher</title>
<link rel="stylesheet" href="github-profile.css" />
</head>
<body>
<div id="username-input" class="username-input">
Username:
<input class="username-input-text" type="text" />
</div>
<div id="github-profile" class="github-profile">
<div class="github-profile-avatar">
<span class="github-profile-username">mmckalan</span>
</div>
<div class="github-profile-name">
Alan Mac Cormack
</div>
<div class="github-profile-location">
Napoli,NA
</div>
<div class="github-profile-stats">
<div class="github-profile-stat">
<i class="icon github-icon-repo" /></i>
<span id = "github-profile-repo-count" class="github-profile-repo-count">50</span>
</div>
<div class="github-profile-stat">
<i class="icon github-icon-gist" /></i>
<span class="github-profile-gist-count">12</span>
</div>
</div>
</div>
<script src="github-profile.js"></script>
</body>
JS:
var usernameInput = document.querySelector('#username-input .username-input-text');
var emptyUser = {
login: "",
name: "",
location: "",
public_repos: "",
public_gists: "",
avatar_url: "notfound.png"
};
usernameInput.addEventListener('change', function(event){
var ghReq = new XMLHttpRequest();
ghReq.addEventListener("load", updateProfileBadge);
ghReq.open("GET", "https://api.github.com/users/" + usernameInput.value);
ghReq.send();
});
function updateProfileBadge() {
var response = JSON.parse(this.reponseText);
if (response.message === "Not Found") {
updateDomWithUser(emptyUser);
} else {
updateDomWithUser(response);
}
}
function updateDomWithUser(user) {
var profile = document.getElementById('github-profile');
profile.querySelector('.github-profile-username').innerText = user.login;
profile.querySelector('.github-profile-name').innerText = user.name;
profile.querySelector('.github-profile-location').innerText = user.location;
profile.querySelector('.github-profile-repo-count').innerText =
user.public_repos;
profile.querySelector('.github-profile-gist-count').innerText =
user.public_gists;
profile.querySelector('.github-profile-avatar')
.style.backgroundImage = "url(" + user.avatar_url + ")";
}
updateDomWithUser(emptyUser);
var quantity = document.getElementById('github-profile-repo-count');
var ul = document.createElement("ul");
document.body.appendChild(ul);
What i'm trying to do is something like this:
The quantity of LI is based on the number given by user.public_repos
But it has to fit to the user repos quantity, so i don't know how to solve it.
Could u please give me a hand?
As far as I know, call to "https://api.github.com/users/NAME" would give you only the number of public respos, not names or stars. For that, you need to call "https://api.github.com/users/NAME/repos" - it may be chained after the first call.
Still, creating X list elements without data is quite easy:
var ul = document.createElement("ul");
document.body.appendChild(ul);
for (var i = 0; i < user.public_repos; i++) {
var li = document.createElement("li");
li.textContent = 'example text';
ul.appendChild(li)
}
Or, if you'll get the repos data itself, in form of array:
var ul = document.createElement("ul");
document.body.appendChild(ul);
repos.forEach((repo)=>{
var li = document.createElement("li");
li.textContent = repo.name;
ul.appendChild(li)
})
Another thing - it's better to write
public_repos: 0,
than empty string.
To create a list of repos, you just have to loop through the JSON data returned by /users/{my_user}/repos. In your case, you need two Ajax calls:
The first one gives you information about the user
The second one gives you information about the user repos
Here is a minimal working example with my repositories:
function get(endpoint, callback) {
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE) {
if (this.status === 200) {
var data = JSON.parse(this.responseText);
callback(data);
} else {
console.log(this.status, this.statusText);
}
}
};
req.open('GET', 'https://api.github.com' + endpoint, true);
req.send(null);
}
function handleUser(data) {
var html = '';
html += '<li>' + data.login + '</li>';
html += '<li>' + data.name + '</li>';
document.querySelector('#user > ul').innerHTML = html;
get('/users/Badacadabra/repos', handleUserRepos);
}
function handleUserRepos(data) {
var html = '';
for (var i = 0; i < data.length; i++) {
html += '<li>' + data[i].name + '</li>';
}
document.querySelector('#repos > ul').innerHTML = html;
}
get('/users/Badacadabra', handleUser);
<div id="user">
<ul></ul>
</div>
<hr>
<div id="repos">
<ul></ul>
</div>

Using for loop to generate text boxes

I want to be able to enter a number into a text box and then on a button click generate that number of text boxes in another div tag and automatically assign the id
Something like this but not sure how to generate the text boxes and assign automatically assign the id
function textBox(selections) {
for (i=0; i < selections +1; i++) {
document.getElementById('divSelections').innerHTML = ("<form><input type="text" id="1" name=""><br></form>");
}
}
Try this one:
function textBox(selections){
selections = selections*1; // Convert to int
if( selections !== selections ) throw 'Invalid argument'; // Check NaN
var container = document.getElementById('divSelections'); //Cache container.
for(var i = 0; i <= selections; i++){
var tb = document.createElement('input');
tb.type = 'text';
tb.id = 'textBox_' + i; // Set id based on "i" value
container.appendChild(tb);
}
}
A simple approach, which allows for a number to be passed or for an input element to be used:
function appendInputs(num){
var target = document.getElementById('divSelections'),
form = document.createElement('form'),
input = document.createElement('input'),
tmp;
num = typeof num == 'undefined' ? parseInt(document.getElementById('number').value, 10) : num;
for (var i = 0; i < num; i++){
tmp = input.cloneNode();
tmp.id = 'input_' + (i+1);
tmp.name = '';
tmp.type = 'text';
tmp.placeholder = tmp.id;
form.appendChild(tmp);
}
target.appendChild(form);
}
Called by:
document.getElementById('create').addEventListener('click', function(e){
e.preventDefault();
appendInputs(); // no number passed in
});
JS Fiddle demo.
Called by:
document.getElementById('create').addEventListener('click', function(e){
e.preventDefault();
appendInputs(12);
});
JS Fiddle demo.
The above JavaScript is based on the following HTML:
<label>How many inputs to create:
<input id="number" type="number" value="1" min="0" step="1" max="100" />
</label>
<button id="create">Create inputs</button>
<div id="divSelections"></div>
See below code sample :
<asp:TextBox runat="server" ID="textNumber"></asp:TextBox>
<input type="button" value="Generate" onclick="textBox();" />
<div id="divSelections">
</div>
<script type="text/javascript">
function textBox() {
var number = parseInt(document.getElementById('<%=textNumber.ClientID%>').value);
for (var i = 0; i < number; i++) {
var existingSelection = document.getElementById('divSelections').innerHTML;
document.getElementById('divSelections').innerHTML = existingSelection + '<input type="text" id="text' + i + '" name=""><br>';
}
}
</script>
Note: Above code will generate the N number of textboxes based on the number provided in textbox.
It's not recommended to user innerHTML in a loop :
Use instead :
function textBox(selections) {
var html = '';
for (i=0; i < selections +1; i++) {
html += '<form><input type="text" id="'+i+'" name=""><br></form>';
}
document.getElementById('divSelections').innerHTML = html;
}
And be carefull with single and double quotes when you use strings
You have to change some code snippets while generating texboxes, Learn use of + concatenate operator, Check code below
function textBox(selections) {
for (var i=1; i <= selections; i++) {
document.getElementById('divSelections').innerHTML += '<input type="text" id="MytxBox' + i + '" name=""><br/>';
}
}
textBox(4); //Call function
JS Fiddle
Some points to taken care of:
1) In for loop declare i with var i
2) your selection + 1 isn't good practice at all, you can always deal with <= and < according to loop's staring variable value
3) += is to append your new HTML to existing HTML.
ID should be generate manually.
var inputName = 'divSelections_' + 'text';
for (i=0; i < selections +1; i++) {
document.getElementById('divSelections').innerHTML = ("<input type='text' id= " + (inputName+i) + " name=><br>");
}
edit : code formated
Instead of using innerHTML, I would suggest you to have the below structure
HTML:
<input type="text" id="id1" />
<button id="but" onclick="addTextBox(this)">click</button>
<div id="divsection"></div>
JS:
function addTextBox(ops) {
var no = document.getElementById('id1').value;
for (var i = 0; i < Number(no); i++) {
var text = document.createElement('input'); //create input tag
text.type = "text"; //mention the type of input
text.id = "input" + i; //add id to that tag
document.getElementById('divsection').appendChild(text); //append it
}
}
JSFiddle

Javascript getting the values of an array of input boxes

I have an input field that has a button to dynamically add another input field and I am trying to get it so that when I click plot i am able to grab the content inside the input fields gps[]
html
<div id="marker">
<input type="text" name="gps[]" id="gps">
<input type="text" name="gps[]">
</div>
Plot
javascript
var counter = 1;
var limit = 3;
function addInput(divName){
if (counter == limit) {
alert("You have reached the limit of adding " + counter + " inputs");
}
else {
var newdiv = document.createElement('div');
newdiv.innerHTML = "<input type='text' name='gps[]'>";
document.getElementById(divName).appendChild(newdiv);
counter++;
}
}
$('body').on('click','.plot', function(){
var y = $('input[name="gps[]"]').val();
console.log(y);
});
You have to use .map to get the value of all the elements in the collection :
var y = $('input[name="gps[]"]').map(function() {return this.value;}).get();
FIDDLE

Categories

Resources