I'm currently trying to get a simple Category System to work.
To do so, I've created a tiny Category "class" which fits my needs:
var categories = [];
function Category (id, name, ownedBy){
this.id = id;
this.name = name;
this.ownedBy = ownedBy;
categories[id] = this;
}
id is, well, the ID of the Category. It's name is only used for display purposed. And "ownedBy" is the ID of the super-category, or "none" if it hasn't one.
After filling my categories-array, I iterate over it and call a function of mine to add the categories to my HTML-Code:
function addHTMLCategory(catID){
var cat = categories[catID]; //Get the Category-"Object"
if(!cat) return; //If it doesn't exist, do nothing.
if(cat.ownedBy != "none"){ //If the category has a supercategory,
addHTMLCategory(cat.ownedBy); //Add it to the HTML first.
}
if(document.getElementById("cat"+catID)) return; //And if it already exists, dont add it again.
//ERROR-PART: If a category has a superclass, get the superclass element.
var contentElement = document.getElementById(cat.ownedBy=="none"?"categories":"cat"+cat.ownedBy);
var li = document.createElement("div");
li.id = "cat"+catID;
li.className = "category";
li.innerText = cat.name;
contentElement.appendChild(li);
}
Initial HTML:
<div id="categories"></div>
This function checks if the Category has a Super-Category, and if yes, it adds this one first: I did this to avoid that the element where the category should be added to doesn't exist.
Unfortunately, exactly this happens: When a Category has a super-category, the "contentElement" variable is null. Could anyone tell me why?
The problem was that the ownedBy variable of Category was set to the name of the super-category, instead of its ID (In another part of the code which I thought was irrelevant)
Related
I have a simple forEach loop in which I'm trying to append list items to an unordered list. However, when I run the script, I'm only seeing one list item being added. Can anyone explain why this is happening?
JS
let bookElement = document.getElementsByClassName("book");
let navElement = document.getElementsByTagName("nav")[0];
let unorderedList = document.createElement("UL");
let listItems = document.createElement("LI");
let book1 = new Book();
let book2 = new Book();
let booksArray = [book1, book2];
createNavigation(booksArray, navElement, unorderedList, listItems);
function createNavigation(booksArray, navElement, unorderedList, listItems){
console.log(booksArray)
booksArray.forEach(function(book){
unorderedList.appendChild(listItems);
})
navElement.appendChild(unorderedList);
}
HTML
<body>
<nav></nav>
<div class="book"></div>
</body>
The log in the function is returning that there are two objects in the array.
You only ever create one list item.
You then append it in multiple places.
Since an element can't exist in multiple places at the same time, each time you append it (after the first) you move it.
Use let listItems = document.createElement("LI"); inside your loop.
Yes, there are two objects in the array, but you're adding the same element to the unorganised list twice. So, the second time it's added, the browser sees that the element is already there and doesn't add it again.
A better approach would be to simply create a new li element in each iteration of the loop:
function createNavigation(booksArray, navElement, unorderedList){
console.log(booksArray)
booksArray.forEach(function(book){
let listItems = document.createElement("LI");
unorderedList.appendChild(listItems);
})
navElement.appendChild(unorderedList);
}
Notice that I've removed the listItems parameter as the value passed into it is now unused.
You can take your program a step further, now, by doing something along these lines:
function createNavigation(booksArray, navElement, unorderedList){
console.log(booksArray)
booksArray.forEach(function(book){
let listItems = document.createElement("LI");
listItems.innerHTML = book.title;
unorderedList.appendChild(listItems);
})
navElement.appendChild(unorderedList);
}
That will create a list of book titles, assuming you have titles stored in a title property in your Book constructor.
When a button is clicked, I am grabbing the current value of a Select control, like so...
$('#myBtn').on('click', function (clickEvent) {
var nameSelected = document.getElementById('mySelectControl').getElementsByTagName('span')[0].innerText;
//...
}
This is fine. The value is correct. Say the value of nameSelected is 'Bob'.
'Bob' also exists elsewhere in my page, in a table. There is more than 1 table, but only 1 of the tables contain the value 'Bob'.
Each table has been assigned the square class.
Here is how I find the names (Bob or otherwise), that are in my tables. I am just doing this in Chrome's Console.
Create an array of each table:
var tables = $('.square').each(function () {
$(this).html();
})
Grab the table at Index 0 and get the name from the table:
var name = $(tables[0]).find('tr:eq(0)').find('td').text();
This all works. The result of the statement above will be 'Bob', or 'Jon', or 'Bill', etc.
What I need is the value of a different td, from whichever table contains nameSelected (from the Select control above). For example pseudo-code:
var phone = $(tables).find('tr:eq(6)').find('td').text();
WHERE
name == nameSelected
I hope that makes sense. Basically trying to get the value of td(6).text from whichever div has nameSelected in td(0).text.
I am just not sure how to write the last statement and I have tried a few things. I want to do all of this when the button is clicked. I hope the pseudo-code helps...
You don't need to create what you called an "array of each tables". You can place your code right inside the each() function and then simply check the name to see if you found who you're looking for (e.g. Bob) and then break so you don't continue searching in the other tables needlessly:
var search = 'Bob';
var phone;
$('.square').each(function() {
var name = $(this).find('tr:eq(0)').find('td').text();
if (name === search) {
phone = $(this).find('tr:eq(6)').find('td').text();
return false; //Break out of the loop.
}
});
I know that the title sounds weird but I don´t know how to exactly describe my problem. I have an array with all the divs id I created before. Now I want to take the first div´s id and remove the div by parentNode.removeChild(); The console prints:
'The "removeChild" property of an undefined or null reference can not be retrieved.'
I hope you can help me with that :)
var animation_time = 1500;
var div_id_selection = [];//it contains 'div0', div1, div2 ... divn
var array_counter = -1;
// Before that is a function that creates a div by document.createElement("div); with the id div0, div1, div2 ...than it writes the id into the array:
div_id_selection.push('div' + id);
var delete_divs = function(){
setTimeout(function(){
array_counter += 1;
var div_to_delete = div_id_selection[array_counter];
//var div_to_delete_str = div_to_delete.toString(); I already tried it with the string-didn´t work
console.log(div_to_delete);
console.log(array_counter);
div_to_delete.parentNode.removeChild(div_to_delete); // here is the problem
}, animation_time);
}
div_to_delete is a string ( id that is stored in the array ).
parentNode method is only available on a DOM object.
You will have to first select the element using the id.
// get the correct DOM object using the array
var elem = document.getElementById(div_to_delete);
elem.parentNode.removeChild(elem);
I am learning extendscript for scripting adobe illustrator.It is very difficult for me to write xml related parsing.
My problem statement is given below:- "I have taken three text boxes namely name,city and country."name" is a unique key.when i click ok button the data must be saved in xml if name does not exist else update the previous name with out creating duplicate.All the names in xml file are displayed in list box.The date of particular name could be deleted by remove button.which will remove data in selected item of list box.
The code i tried to do is:-
var myWindow = new Window ("dialog", "Form");
var txt1 = myWindow.add ("edittext");//name unique
var txt2 = myWindow.add ("edittext");//city
var txt3 = myWindow.add ("edittext");//country
var btn=myWindow.add ("button", undefined, "OK");
btn.onClick = function () {
for (i=0;i<numberofnamesinxml;i++)//coding required
{
if(txt1.text!=xmlname[i]) // to verify name not there since it is like primary key
xmlFile.open("a");
xmlFile.write(root.toXMLString());
xmlFile.copy ('C:/data.xml');
xmlFile.close();
//myList refresh
}
}
var myList = myWindow.add ("listbox");
for (i=0;i<numberofnamesinxml;i++)//coding required
{
config='C:/data.xml';
config.open("r");
data= xmlname[i] //here i need to set data to
config.close();
myList.add ("item", data);
}
var btn1=myWindow.add ("button", undefined, "remove");
btn1.onClick = function () {
myList.remove (myList1.selection[i]);
//xml data having this list name must be removed
}
myWindow.show ();
Please kindly help me.
This should not be considered a full answer. I still post it because it might help finding one.
This is what I tried to write as an answer. The read/write part works but the checking of an element exists fails.
if the child is not an exact match, xml.contains(xml) will not return true.
var path = '~/Desktop/test.xml';
var xmlfile = File(path);
if (!xmlfile.exists) {
$.writeln('xml file does not exist. Creating new one');
xmlfile = new File(path);
xmlfile.open('w');
xmlfile.write('<Root></Root>');
xmlfile.close();
}
xmlfile.open('r');
xmlcontent = xmlfile.read();
xmlfile.close();
//$.writeln(xmlcontent);
var xml = new XML(xmlcontent);
// here the problems start
// the check is only working for known elements
var child = new XML('<name data="bob"></name>');
if (xml.contains(child)) {
child.#data = 'jim';
$.writeln('A child called "name" exists. Update');
xml.replace('name', child);
} else {
$.writeln('no child called "name" exists. Append');
child.#data = 'bob';
xml.appendChild(child);
}
xmlfile.open('w');
xmlfile.write(xml.toXMLString());
xmlfile.close();
My real answer is:
Use JSON instead.
i'm working in a simple program that uses an HTML Form to fill an Array with some information, so far, i can get the input data, store it into my list, and visualize it like this :
It basically, converts the Name to a Link, when you click it, it will create a <div> in which i show all the information of the contact.
And i've done this like this :
The error i'm getting is in the last 6 lines of Code.
(I'm trying to avoid all non-troubling code)
var list = [];
var ulList = document.createElement("UL");
function AddToList(){
//Just pushes the info into the list.
}
function Visualize(){
ClearScreen();
for(var i = 0 ; i < list.length ; i++){
//Tried to keep it clean, this just works with each item in the list.
AddToList(i);
}
}
//This Works correctly, it shows every Name i've previously pushed into the list like a Link.
function AddToList(index){
var element = document.createElement("LI");
var name = document.createTextNode(list[index].name);
element.appendChild(name);
var link = document.createElement("A");
link.setAttribute("HREF", "#");
link.appendChild(element);
lik.setAttribute("ID", index);
link.addEventListener("click", ShowInfo(this.id)); //Index would do the same
ulList.appendChild(link);
document.getElementsByTagName("body")[0].appendChild(ulList);
}
//Trouble comes here
function ShowInfo(index){
CleanDIV();
//Previously created <div> with box as id
var box = document.getElementById("box");
var details = document.createElement("UL");
var lName = document.createElement("LI");
var lNumber = document.createElement("LI");
var lMail = document.createElement("LI");
//
//The error is here : Cannot Read Property 'name' of undefined
//And i dont know why, since i've done something similar in a previous line...
//
lName.appendChild(document.createTextNode("Name :" + list[index].name));
lNumber.appendChild(document.createTextNode("Number : " + list[index].number));
lMail.appendChild(document.createTextNode("Mail : " + list[index].mail));
details.appendChild(lName);
details.appendChild(lNumber);
detaisl.appendChild(lMail);
}
I dont even know what kind of mistake i'm making, and was not sure of how to ask this question.
I apologyze for any grammar mistake, my bad variable naming abilities and any lack of quality in my question.
Thank you kindly.
In your AddToList function, indice is 'undefined'
You get the error because you have not added anything to your list array. Add the person details to the list array when the Add to List button is clicked. And retrieve this when the link is clicked.
var name = document.getElementById("txtName").value;
var number = document.getElementById("txtNnumber").value;
...
var person = {'name': name, 'number': number};
list.push(person);
Looks like you have a couple of typos in your code.
lik.setAttribute("ID", indice);
link.addEventListener("click", ShowInfo(this.id)); //Index would do the same
should be
link.setAttribute("ID", index);
link.addEventListener("click", ShowInfo(index)); //Index would do the same