create HTML using javascript recursive function not working - javascript

I am trying to make a recursive function in Javascript which should basically give me HTML like BELOW
<li><a class="expand">+</a> <span class="treeNodeInner"><a id="7471">Ringtones</a>
<ul>
<li><span class="treeNodeInner"><a id="7995">Top Tones</a></span></li>
<li><span class="treeNodeInner"><a id="8642">Country</a></span></li>
<li><span class="treeNodeInner"><a id="8640">Rock</a></span></li>
</ul>
</span></li>
I am using the below function to make the above html using javascript.
Its basically a tree view were we will have nodes and sub nodes kind of thing.
I am struggling the achieve the above HTML structure through below function, please advise modifications with the below function
function GenerateNodes(categItem) {
var parentNode = "<li>"; //parent li
if (categItem.SubCategory != null && categItem.SubCategory != undefined && categItem.SubCategory.Count > 0) {
parentNode = "<li><a class='expand'>+</a>";
}
parentNode += "<input type='radio' name='category' /><span class='treeNodeInner'><a id='" + categItem.ID + "'>" + categItem.name + "</a> "; //need to close the span
if (categItem.SubCategory != null && categItem.SubCategory != undefined && categItem.SubCategory.Count > 0) {
var subNode = "<span><ul>";
for (var index = 0; index < categItem.SubCategory.Count; index++) {
subNode += GenerateNodes(categItem.SubCategory[index]);
subNode += "</ul></span>"
}
parentNode += subNode
}
parentNode += "</span></li>"
}
Thanks

Simply looking at the code, I found out that you are not inserting the new li in your html. I'm not sure if you manage this somewhere out of your code. I'd copied your code and do some debug on it. Then I try to add the li on the html using some code. See code below:
//Insert this after parentNode += "</span></li>";
var newDiv = document.createElement('div');
newDiv.innerHTML = parentNode;
categItem.appendChild(newDiv.childNodes[0]);
//I assume that categItem is the id of the container as your sample html code
//above is not clear to me. So I did using sample html below
<div id="liContainer">
</div>
See this jsfiddle how the above code work. I know this is not exactly what you want, but I hope you can get some idea from this.

Related

How to make columns with collapsible ul and li tags dynamically?

I am currently using the following two functions to dynamically create a collapsible list from an object which contains info on the individual parts within the object. I have also included a checkbox for each item in the collapsible list, but that check box always appears right next to the names. I would prefer these checkboxes to be in the same row as the list item, but in a separate column so that it looks neater. I might also add more columns later on with material info. So I was trying to figure out how I can do this with my current setup below or if there was a better way to achieve what I want instead of using my list.
<div class="objtree"></div>
function check(obj) {
var html = '';
var name = obj.name ? obj.name +' (' +obj.type+')' : obj.type;
html +='<div class="node">'
html += '<li class="ntitle">' + name + '<input type="checkbox" name="'+(obj.id-id)+'" value="checked" onchange="snap(this)"/></li>';
if (obj.children) {
html += '<ul class="children hide">';
for (var i = 0; i < obj.children.length; i++) {
html += check(obj.children[i],)
}
html += '</ul>';
}
html += "</div>";
return html;
}
function assignEvent() {
$('.ntitle').click(function () {
var p = $(this);
var c = p.parent().find('.children:first')
if (c.hasClass('hide')) {
c.removeClass('hide');
p.addClass('open');
}
else {
c.addClass('hide');
p.removeClass('open');
}
})
}
The following is what I currently have which is collapsible if I click on the items:
And I am trying to achieve the following:

How to add new <li> element each click?

First attempt at any sort of Javascript so be gentle aha
Have managed to have the page add the new list item to the inner html of an unordered list, but each time after that it just replaces the initial.
I feel like I'm missing something really basic here?
Any advice would be greatly appreciated.
<script>
function addItem() {
var item = document.getElementById("task-field").value;
document.getElementById("task-list").innerHTML = "<li> " + item + " </li>";
}
</script>
Use
document.getElementById("task-list").innerHTML += "<li> " + item + " </li>";
instead of
document.getElementById("task-list").innerHTML = "<li> " + item + " </li>";
The += operator will use the current value of innerHTML and append your new content in this case. This as suggested by #Hassam Imam.
Another way of doing it is using appendChild() creating the new <li> item through JS. Like this:
function addItem() {
let item = document.getElementById("task-field").value;
let parent = document.getElementById("task-list");
// Create new node.
let li_item = document.createElement("li");
li_item.innerHTML = item;
// Append child.
parent.appendChild(li_item);
}
But this last method is probably too lengthy. The += solution seems good. Just another way of doing it.
<script>
function addItem(item) {
const li = document.createElement('li');
li.innerHTML = `${item}`;
li.id = 'task-field';
document.getElementById('task-list').appendChild(li);
}
</script>

Javascript/JQuery Dynamic UL Troubles

I have been working on a problem adding dynamic UL and LI's to a webpage through javascript and jQuery and am stumped.
I almost have a solution but it's not adding the styling and it is not putting each UL on a separate line. I have a feeling that the tags I am creating are not closing but I'm not sure.
My end goal is to have each JSON line as a separate UL and showing on a separate line, with the first name + last name + phone number as the list items of each UL and displaying like a table (without using a table). No inline styles and no HTML markup other than whatever is added dynamically through Javascript.
I was given the following code as a starting point but my solution has definitely veered a little off course. I have searched for hours and so far you can see my best attempt at the jsfiddle link below. Any help is greatly appreciated.
function showContacts(data){
var markup = "";
$("body").html(markup);
};
$(document).ready(function myFunction() {
var jsonText = '[ {"firstname":"Bill","lastname":"Gates","phone":"123-456-7891"}, {"firstname":"Steve","lastname":"Jobs","phone":"198-765-4321"}, {"firstname":"Kevin","lastname":"Spencer","phone":"007-008-0099"}, {"firstname":"David","lastname":"Zimmerman","phone":"800-256-6321"}, {"firstname":"Bert","lastname":"Ernie","phone":"127-624-1138"}, {"firstname":"Guy","lastname":"Lafleur","phone":"806-797-4213"} ]';
showContacts(jsonText);
});
https://jsfiddle.net/bkweLctq/embedded/result/
You just missed element creation.
Your odd & even class style also needs to be changed.
Updated js
function showContacts(data) {
var markup = "";
var jo = $.parseJSON(data);
console.log(jo);
var $body = $('body');
var _html = '';
for(var i = 0; i<jo.length; i++){
if((i+1)%2 == 0 ){
_html += '<ul class="even">';
}else {
_html += '<ul class="odd">';
}
var _index = 0;
$.each(jo[i], function(k,n) {
if((_index+1)%2 == 0 ){
_html += '<li class="even"> '+ n +' </li>'
}else {
_html += '<li class="odd"> '+ n +' </li>'
}
_index++;
});
_html += '</ul>';
}
$body.html(_html);
};
$(document).ready(function myFunction() {
var jsonText = '[ {"firstname":"Bill","lastname":"Gates","phone":"123-456-7891"}, {"firstname":"Steve","lastname":"Jobs","phone":"198-765-4321"}, {"firstname":"Kevin","lastname":"Spencer","phone":"007-008-0099"}, {"firstname":"David","lastname":"Zimmerman","phone":"800-256-6321"}, {"firstname":"Bert","lastname":"Ernie","phone":"127-624-1138"}, {"firstname":"Guy","lastname":"Lafleur","phone":"806-797-4213"} ]';
showContacts(jsonText);
});
I have also updated your fiddlejs link

Finding element using its innerHTML

Please have a look to this DOM Tree...
<div>
<div>
<span> Home1 </span>
</div>
<span> Home2 </span>
<span> Home3 </span>
</div>
Now suppose I have a scenario where somehow I got the innerHTML of first span Home1.
Is it possible to get the element span and its parent div by using only this (Home1) information.
Here is what you want.
Here is html:
<label>opal fruits</label>
Here is jQuery:
$("label:contains(opal fruits)")
var mySpans = document.getElementsByTagName(span);
for(var i=0;i<mySpans.length;i++){
if(mySpans[i].innerHTML == 'Home1'){
var parent = mySpans[i].parentNode;
break;
}
}
this selects the parent of span having innerHTML Home1
There are so many ways to get info about your elements.
Using the innerHTML as an identifier is not a good solution.
You probably need some sort of event to that makes you search for that "Menu1"
So here is a click handler that works also on other events that give you information about what you have clicked.
function handler(e){
var txt='You clicked on a '+e.target.nodeName+'\n';
txt+='The innerHTML is '+e.target.innerHTML+'\n';
txt+='The text is '+e.target.textContent+'\n';
txt+='The parentNode is '+e.target.parentNode.nodeName+'\n';
alert(txt)
}
document.addEventListener('click',handler,false)
DEMO
function handler(e) {
var txt = 'You clicked on a ' + e.target.nodeName + '\n';
txt += 'The innerHTML is ' + e.target.innerHTML + '\n';
txt += 'The text is ' + e.target.textContent + '\n';
txt += 'The parentNode is ' + e.target.parentNode.nodeName + '\n';
alert(txt)
}
document.addEventListener('click', handler, false)
<div>
<div><span>Menu1</span></div><span>Menu2</span><span>Menu3</span>
</div>
If you want that your script searches for that "Menu1" you should consider adding that "Menu1" as an attribute on the span or parentNode.
<div id="Menu1">
<span>Home1</span>
</div>
and then call
document.getElementById('Menu1');
Which is very fast.
innerHTML method return String type. It don't associate with DOM tree.
You can use jQuery and it contains selector(fiddle):
$(":contains('Home1')").last()
var divRef; //Reference to the container of your div / span elements
var spans = divRef.getElementsByTagName("span");
var spanContainer;
for(var i = 0; i < spans.length; i++){
if(spans[i].innerHtml == "Home 1"){
spanContainer = spans[i].parentNode;
break;
}
}
if(spanContainer){
alert("Element has been found!");
}
function findNodeByInnerHTML(nodelist, innerHTML){
for(let ii = 0; ii < nodelist.length; ii++){
if(nodelist[ii].innerHTML === innerHTML)
return nodelist[ii]
}
}
let span = findNodeByInnerHTML(document.querySelectorAll('span'), 'home')

Using innerHTML to add ordered list fails in IE

I'm using the following Javascript code to populate a DIV with an ordered list:
// send script back in split list
var scriptList = script.split("\n");
var finalScript = "<ol>\n";
var count = 0;
while(scriptList.length >= count) {
if((scriptList[count]=="") || (scriptList[count] == undefined)) {
count ++;
continue;
}
finalScript = finalScript + "<li>" + scriptList[count] + "</li>\n";
count ++;
}
finalScript = finalScript + "</ol>";
scriptingDiv.innerHTML = finalScript;
In firefox, if i look in the DOM using Firebug, this correctly translates to the following and correctly displays an ordered list.
<ol>
<li>This is the first item in the list</li>
<li>This is the second item in the list</li>
</ol>
In IE, it displays as if the </li> tags are <br /> tags and ignores all the other tags, like this:
This is the first item in the list
This is the second item in the list
Do I need to dynamically add the ordered list to the DOM for this to work? As opposed to just setting the html code in the div using .innerHTML?
TIA
Do I need to dynamically add the ordered list to the DOM for this to work? As opposed to just setting the html code in the div using .innerHTML?
Yes
var scriptList = script.split("\n");
var count = 0;
var ol = document.createElement("ol");
for(var index=0; index<scriptList.length; index++) {
if(scriptList[index]!="") {
var li = document.createElement("li");
li.innerHTML=scriptList[index];
ol.appendChild(li);
}
}
scriptingDiv.appendChild(ol);
Why not use dom methods instead? IE:
myOL = document.createElement("ol");
myLI = document.createElement("li");
myTxt = document.createTextNode("My Text!");
myLI.appendChild(myTxt);
myOL.appendChild(myLI);
etc

Categories

Resources