So I'm trying to create a list of input with unique values which are gotten from a array of objects. But for some reason it only iterates once and stops.
function loadLayer() {
//Get the object from local storage
var project = JSON.parse(localStorage.getItem('project'));
var projectLayers = project.layers
for (var x = 0; x < projectLayers.length; x++) {
var x = createLayer(projectLayers[x].name)
appendLayer(x)
}
}
So project layer is basically an array like [{id=1,name="bob},{id=2,name="kevin"}]
function createLayer(name) {
var li = document.createElement("li");
li.className = "list-group-item"
var x = document.createElement("INPUT")
x.setAttribute("type", "text")
x.setAttribute("value", name)
li.appendChild(x)
return li
}
function appendLayer(layer) {
var layerList = document.getElementById("layerList")
layerList.appendChild(layer)
}
and appendlayer just adds the li to the ul
However, after i run the program my only has one with a input with bob inside it. Where did the other no go. I tried printing to see if second loop was called but it didn't seem like it. I don't know why and been stuck for hours.
Just like you have been told, you need to be careful with the way you name variables.
Secondly I will also suggest using let instead of var. Because you could easily overwrite a variable declared with var outside its initial scope.
And now to your code:
I made some edit to your code especially the loadLayer function and it appends both names to the list:
<script>
let projectList = [
{
id:1,
name:"bob"
},
{
id:2,
name:"kevin"
}
]
function loadLayer() {
window.localStorage.setItem('project', JSON.stringify(projectList));
let p = JSON.parse(window.localStorage.getItem('project'));
for (let i = 0; i < p.length; i++) {
let projectName = createLayer(p[i].name)
appendLayer(projectName)
}
}
function createLayer(name) {
let li = document.createElement("li");
li.className = "list-group-item"
let x = document.createElement("INPUT")
x.setAttribute("type", "text")
x.setAttribute("value", name)
li.appendChild(x)
return li
}
function appendLayer(layer) {
let layerList = document.getElementById("layerList")
layerList.appendChild(layer)
}
loadLayer()
</script>
You are naming the variable of the iteration in the loop as x and the var x = createLayer(projectLayers[x].name) conflicts with it, change one of them.
Related
I'm looping through some elements by class name, and adding event listeners to them. I then grab the id of the selected element (in this case "tom"), and want to use it to find the value of "role" in the "tom" object. I'm getting undefined? can anyone help?
var highlightArea = document.getElementsByClassName('highlightArea');
for (var i = 0; i < highlightArea.length; i++) {
highlightArea[i].addEventListener("mouseover", showPopup);
highlightArea[i].addEventListener("mouseover", hidePopup);
}
function showPopup(evt) {
var tom = { title:'tom', role:'full stack man' };
var id = this.id;
var role = id.role;
console.log(role)
}
You are not selecting the elements correctly, the class is hightlightArea and you are querying highlightArea (missing a 't'), so, no elements are found (you can easily discover that by debugging or using console.log(highlightArea) that is the variable that holds the elements found.
Just because the id of an element is the same name as a var, it doesn't mean that it have the properties or attributes of the variable... So when you get the Id, you need to check which one is and then get the variable that have the same name.
Also, you are adding the same listener two times mouseover that way, just the last would work, it means just hidePopup. I changed to mouseenter and mouseleave, this way will work correctly.
After that, you will be able to achieve your needs. Below is an working example.
var highlightArea = document.getElementsByClassName('hightlightArea');
var mypopup = document.getElementById("mypopup");
var tom = { title:'tom', role:'marketing'};
var jim = { title:'jim', role:'another role'};
for (var i = 0; i < highlightArea.length; i++) {
highlightArea[i].addEventListener("mouseenter", showPopup);
highlightArea[i].addEventListener("mouseleave", hidePopup);
}
function showPopup(evt) {
let ElemId = this.id;
let role;
let title;
if (ElemId == 'tom'){
role = tom.role;
title = tom.title;
}else if (ElemId == 'jim'){
role = jim.role;
title = jim.title;
}
let iconPos = this.getBoundingClientRect();
mypopup.innerHTML = role;
mypopup.style.left = (iconPos.right + 20) + "px";
mypopup.style.top = (window.scrollY + iconPos.top - 60) + "px";
mypopup.style.display = "block";
}
function hidePopup(evt) {
mypopup.style.display = "none";
}
<div class="hightlightArea" id="jim">Div Jim</div>
<div class="hightlightArea" id="tom">Div Tom</div>
<div id="mypopup"></div>
in your function 'showPopup' you have this:
var id = this.id
but this.id is not defined. You probably meant to write this:
var title = dom.title;
I have a firebase database and in their all users their friends are stored (value is true if they are friends). But if the other person hasn't accepted the friend request yet, the value is false.
I can put all those users in a list. But what I want to achieve is that only the users with value 'true' are showed and those with value 'false' not.
var ref = firebase.database().ref("friends").child(userUID);
ref.on('value', gotFriends);
function gotFriends(data) {
var usernames = data.val();
var names = Object.keys(usernames);
for (var i = 0; i < names.length; i++) {
var uname = names[i];
var ul = document.getElementById("friendsList");
var li = document.createElement('li');
li.appendChild(document.createTextNode(uname));
ul.appendChild(li);
}
}
Thank you in advance!
Something like this should work:
function gotFriends(snapshot) {
snapshot.forEach(function(friend) {
var uname = friend.key;
if (friend.val() === true) {
var ul = document.getElementById("friendsList");
var li = document.createElement('li');
li.appendChild(document.createTextNode(uname));
ul.appendChild(li);
}
}
}
In addition to the if, this code uses Snapshot.forEach() to loop over the results. It doesn't change the behavior, but is slightly faster and more idiomatic.
I have a ToDo list, using localStorage... I need to be able to remove the item from the ToDo list... I try to use "dataArray.splice();" But the problem is I don't know how i can remove the object when the position is unknown...
function getTodoItems() {
for (var i = 0; i < dataArray.length; i++) {
if (!dataArray[i].listItem.length) return;
var itemList = document.getElementById("my-todo-list");
var list = document.createElement("li");
itemList.appendChild(list);
list.innerHTML = dataArray[i].listItem;
var spanItem = document.createElement('span');
spanItem.style.float = 'right';
var myCloseSymbol = document.createTextNode('\u00D7');
spanItem.classList.add("closeBtn");
spanItem.appendChild(myCloseSymbol);
listItems[i].appendChild(spanItem);
close[i].onclick = function() {
var div = this.parentElement;
div.style.display = "none";
console.log(dataArray);
}
var list = document.getElementsByTagName('li');
list[i].onclick = function() {
this.classList.toggle("checked");
}
}
}
Then probably get its position:
const position = dataArray.indexOf(/*whatever*/);
dataArray.splice(position, 1);
You can get the position of the element using 'indexOf'
let pos = dataArray.indexOf(element);
dataArray.splice(pos,1)
IndexOf() wont work if you are trying to find the index of an entire object or array inside the array.
If you need to find the index of an entire object inside your array, you test each one's value to find out if it is the correct one. I would use findIndex();
Try this in your console:
var array = [];
for (var i = 0; i < 10; i++ ){ array.push({item: i}) }
console.log('Current Array: ', array);
var indexOfResult = array.indexOf({item: 3});
console.log('indexOf result: ',indexOfResult);
var findIndexResult = array.findIndex(object => object.item === 3);
console.log('findIndex result: ',findIndexResult)
Following the documentation sample, I'm trying to create a function that searchs for a numerated list in a google document and, if finds it, adds a new item to that list. But I get this error: Cannot find method setListId(string). (line 21, file "test") or, if I change line 21 content (replacing elementContentfor newElement), I get the message: Preparing for execution... and nothing happens. How to fix it?
This is my code:
function test() {
var elementContent = "New item testing"; // a paragraph with its formating
var targetDocId = "1R2c3vo9oOOjjlDR_n5L6Tf9yb-luzt4IxpHwwZoTeLE";
var targetDoc = DocumentApp.openById(targetDocId);
var body = targetDoc.getBody();
for (var i = 0; i < targetDoc.getNumChildren(); i++) {
var child = targetDoc.getChild(i);
if (child.getType() == DocumentApp.ElementType.LIST_ITEM){
var listId = child.getListId();
var newElement = body.appendListItem(elementContent);
newElement.setListId(newElement);
Logger.log("child = " + child);
}
}
}
Following my comment, I tried to play with your script to see what happened and I came up with that code below...
I'm not saying it solves your issue and/or is the best way to achieve what you want but at least it gives a result that works as expected.
Please consider it as a "new playground" and keep experimenting on it to make it better ;-)
function test() {
var elementContent = "New item testing"; // a paragraph with its formating
var targetDocId = DocumentApp.getActiveDocument().getId();
var targetDoc = DocumentApp.openById(targetDocId);
var body = targetDoc.getBody();
var childIndex = 0;
for (var i = 0; i < targetDoc.getNumChildren(); i++) {
var child = targetDoc.getChild(i);
if (child.getType() == DocumentApp.ElementType.LIST_ITEM){
while(child.getType() == DocumentApp.ElementType.LIST_ITEM){
child = targetDoc.getChild(i)
childIndex = body.getChildIndex(child);
Logger.log(childIndex)
i++
}
child = targetDoc.getChild(i-2)
var listId = child.getListId();
Logger.log(childIndex)
var newElement = child.getParent().insertListItem(childIndex, elementContent);
newElement.setListId(child);
break;
}
}
}
I have a script where I'm appending elements to a list. I would need that when I click the element a function is called, and for this function the value of a variable when creating the li is needed (it's the li content).
I've checked solutions like adding newLi.onclick = function(){...}.
The problem with this solution is that I'm not getting the right value in the function, I get the value of another element in the list.
Right now this is how I'm creating the elements:
var ULlist = document.getElementById('ULid');
for(i=0;i<data.length;i++){
var Value = data[i] //function to get data
var newLi = document.createElement('li');
newLi.appendChild(elements.createTextNode(Value));
newLi.onclick = function(){alert(Value)} //not displaying the right value
ULlist.appendChild(newLi);
}
So the question is, is there any way to create te onclick event giving to the element the right value of the variable?
Edit: I've added a portion more of code.
Li's are being created, and information displayed correctly, the only problem is when trying to create the event that it's not giving the right value, that should be the value cointained at the li
You can achieve this by creating function inside and keeping the value in the scope of that function.
var data = [10, 20, 30, 40, 50, 60, 70];
addItems = function() {
var list = document.getElementById("list");
for (var i = 0; i < data.length; i++) {
var newLi = document.createElement("li");
newLi.innerHTML = i + 1;
list.appendChild(newLi);
(function(value){
newLi.addEventListener("click", function() {
alert(value);
}, false);})(data[i]);
}
}
jsfiddle : http://jsfiddle.net/Qf5JZ/1/
Use DOM2 event listeners, in particular the element.addEventListener API:
function clickHandlerFor(data) {
return function(event) {
var li = event.target;
// do something with data and li.
};
}
for (...) {
var Data = ... //function to get data
var newLi = elements.createElement('li');
newLi.appendChild(elements.createTextNode(Data));
newLi.addEventListener("click", clickHandlerFor(Data), false);
ULlist.appendChild(newLi);
}
Another option is much simpler: use the TextNode value in your handler:
function handler(event) {
var dataValue = event.target.firstChild.nodeValue; // value of TextNode created by elements.createTextNode(Data)
// handle dataValue
}
newLi.addEventListener("click", handler, false);
When I experienced this problem, I solved it like this:
var ULlist = document.getElementById('ULid');
for(var i=0; i<data.length; i++){
var index = i;
(function() {
var Value = data[index] //function to get data
var newLi = document.createElement('li');
newLi.appendChild(elements.createTextNode(Value));
newLi.onclick = function() { ... };
ULlist.appendChild(newLi);
}());
}
Edit: Today, I remember another thing about for scope. It is another solution to send parameter 'i' to function inside the loop:
var ULlist = document.getElementById('ULid');
for(var i=0; i<data.length; i++){
(function(index) {
var Value = data[index] //function to get data
var newLi = document.createElement('li');
newLi.appendChild(elements.createTextNode(Value));
newLi.onclick = function() { ... };
ULlist.appendChild(newLi);
}(i));
}
Try this and let me know if it works.