Questions about how to use javascript to increase virtual nodes - javascript

I have a set of ui and li structures. Currently, I have a requirement to concatenate the API to form 4 lis of data and put them behind the original li to add! I use the appendChild method, but you need to use this method first Create a node let div = document.createElement('div'); But this will cause the newly created label to add a div, which is a label I don't want. I would like to ask if it is possible to create a virtual empty node and put li in it ? I don't know how to do it specifically, and hope to get your help. I wrote an example such as the following case code to simulate my problem, thank you PS: I have tried to use innerHTML, but this will overwrite the original content when adding data in my actual project, so it does not work .
let str;
let wrap = document.querySelector('.wrap');
let div = document.createElement('div');
str += `<li>5555</li>
<li>6666</li>
<li>7777</li>
<li>8888</li>
`
div.innerHTML = str;
wrap.appendChild(div);
<ul class="wrap">
<li>1111</li>
<li>2222</li>
<li>3333</li>
<li>4444</li>
</ul>

Is it possible to create a virtual empty node and put <li> elements in it?
Yes, this exactly what a DocumentFragment does. Once you append the fragment to the <ul>, the intermediate "virtual" node is skipped and its contents are transferred.
However, a fragment does not have an .innerHTML property. For your use case, better use insertAdjacentHTML:
const wrap = document.querySelector('.wrap');
const str = `<li>5555</li>
<li>6666</li>
<li>7777</li>
<li>8888</li>
`;
wrap.insertAdjacentHTML('beforeend', str);
<ul class="wrap">
<li>1111</li>
<li>2222</li>
<li>3333</li>
<li>4444</li>
</ul>

You added the jquery tag, so I am going to use it because it's easier that way. With jQuery you can add multiple <li> tags at once, which is preferred because each DOM update is expensive.
let html = `<li>5555</li>
<li>6666</li>
<li>7777</li>
<li>8888</li>`;
$('.wrap').append(html);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="wrap">
<li>1111</li>
<li>2222</li>
<li>3333</li>
<li>4444</li>
</ul>

Related

Target and alter anchor element test and attributes nested with vanilla JavaScript

I have a nested <a> element that I want to change the text and attributes for.
So far I am getting the a tag and setting the innerHtml to something else. However I feel this might be bad practise.
Heres the code I need to target and change
<li class="promo-bar">
<div>
<span class="icon-with-text">
// I want to change this a element
Free delivery
</span>
</div>
</li>
This what I have tried so far that does work. However I feel that either using innerHtml may be bad practise or that there is a cleaner way that is more descriptive.
var newLink = document
.querySelector(".promo-bar ")
.children[0].querySelector("a");
var myNewLinkHtml = `
<a
class="newClassName"
href="#"
id="new-id"
>Why choose us?</a
>
`;
newLink = newLink.innerHTML = myNewLinkHtml;
I would like to get the <a> element and change the text and have the ability to add class names and custom attributes.
If using innerHtml is ok then great, else my aim is to use only Vanilla Javascript methods to achieve this.
You can access each property independently and update them as you need.
For the content use textContent.
To add classes, classList.add().
The id can be updated assigning a new one.
const el = document.querySelector('.promo-bar a');
el.id = 'new-id';
el.classList.add('new-class');
el.textContent = 'New content';
<li class="promo-bar">
<div>
<span class="icon-with-text">
// I want to change this a element
Free delivery
</span>
</div>
</li>
If you want to use ready html instead of editing the text and each property your best bet is to place that html in a temporary element and then replace the original link with the one(s) created in the temporary element.
var newLink = document.querySelector(".promo-bar>:first-child a");
// `document.querySelector(".promo-bar a")` would probably work as well, but I don't know what your whole html looks like and used `.children[0]`
var temp = document.createElement("div");
temp.innerHTML = `<a class="newClassName" href="#" id="new-id">Why choose us?</a>`;
// using while is safer in case more than 1 nodes are added using `innerHTML = "..."`
while (temp.childNodes.length) newLink.parentElement.insertBefore(temp.firstChild, newLink);
newLink.remove();
<li class="promo-bar">
<div>
<span class="icon-with-text">
// I want to change this a element
Free delivery
</span>
</div>
</li>
General tip about innerHTML: try to avoid altering the innerHTML of the main dom tree as it could remove event listeners and change references to dom objects.

Append values to a specific element in a string with Jquery

I have an element in local storage with multiple elements, for simplicity, I will make the element:
<div id="outer">
<ul id="inner">
<li id="item">
</li>
</ul>
</div>
The element is saved as a string and I want to manipulate the contents.
Like such:
let local_storage_element = localStorage.getItem("val")
$(local_storage_element+':last-child').append("<p>something</p>")
No matter what selector I add after local_storage_element it will always append the value to the string not to the selected element(:last-child in this case)
does anyone know how to append to a specific element within the string??
Although you have written jquery in the title there is a javascript tag added also so I thought why not provide an answer that justifies your needs and helps you accomplish the task in the same way you want.
The
DocumentFragment interface represents a minimal document object that has no parent. It
is used as a lightweight version of Document that stores a segment of
a document structure comprised of nodes just like a standard document.
The key difference is that because the document fragment isn't part of
the active document tree structure, changes made to the fragment don't
affect the document, cause reflow, or incur any performance impact
that can occur when changes are made.
So how to do it as the DocumentFragment still appends node with it and not string, we will create a temp element and add the HTML from the localStorage using innerHtml and then append the firstChild of that temp node i.e our actual string which is now treated as a node, to the document fragment and then search and appends HTML to it, we will use our temp element to add HTML every time see below.
I will append a new child div to the element #outer in the string given above in the post here is the working FIDDLE as SO does not support localStorage you can see it working there open the console to view the resulting HTML with the new child added and below is the code
$(document).ready(function () {
if (localStorage.getItem('html') === null) {
localStorage.setItem('html', '<div id="outer"><ul id="inner"><li id="item"></i></ul></div>');
}
var frag = document.createDocumentFragment();
var temp = document.createElement('div');
temp.innerHTML = localStorage.getItem('html');
frag.appendChild(temp.firstChild);
temp.innerHTML = '<div class="new-child"></div>'
frag.querySelector("#outer").appendChild(temp.firstChild);
console.log(frag.querySelector("#outer"));
localStorage.removeItem('html');
});
You can't use string as selector. If you want transform string to html then you should put it in some element as innerHTML. So try create some hidden div and insert your string as HTML to it. Something like this
var your_string = '<ul><li>1</li><li>2</li><li>3</li><li>4</li></ul>';
document.querySelector('.hidden').innerHTML = your_string;
document.querySelector('ul li:last-child').innerHTML = 'your content';
document.querySelector('.result').appendChild(document.querySelector('ul'));
Example
The problem may arise when you get '<div id="outer">' from localStorage to use it as a selector since it only accepts "#outer" to be a selector. If you want to add an element to be the last child of parent's element, you could use after() instead of append().
$(document).ready(() => {
if ($("#charl").children().length === 0)
{
// if using after with no element inside ul then it will be inserted after il
$("#charl").html("<li>foo</li>")
}
else {
$("#charl li").after("<li>bar</li>")
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="charl">
<li>Foo</li>
</ul>

Obtaining Upper level li text

So I currently have a list like so on my page
<li class="head">
<b>Introduction</b>
<ul>
<li class="sub">somethingsomething</li>
</ul>
</li>
This list is being used with sortable, so the user can decide on the order, and I am passing this information to a grails controller for use in application logic. So, I am trying to read it in, and place the text contained in the "head" and "sub" classes in 2 different arrays. However, when I use a jquery selector to obtain the head elements, and obtain the text attribute of the element, it contains the inside list as well.
$('#divname').find("ul > li.head").each(function()
{
var current = $(this);
console.log(current.text());
});
results in Introductionsomethingsomething
Is there any way to only obtain the 'Introduction' text from the list, and ignore the text in the nested <ul> and <li.sub>? Due to it being nested, I am unable to figure out how to use jQuery's :not() selector
You can find the b tag using jquery tagname selector.Like this:
var current = $(this).find('b');
console.log(current.text());
Working Demo
May be this is solution:
<script>
$('#divname').find("ul > li.head").each(function()
{
var current = $(this).find("b");
console.log(current.text());
});
</script>

Save the parents children in a var to append later

I have a markup in one of my website pages as follows:
<div id="mainPage">
<div>
<div><ul><li>etc.</li></ul>
</div>
<div>
<div><ul><li>etc.</li></ul>
</div>
</div>
What the above means is that there's a main div in my website which has the content. I want to take all the children of the particular div and save it in a var, since I want to use that var later for something like $('resurrectPage').append(someVar); where someVar has the dom elements from the main page div.
How can all the children of a particular element be selected and added to a var?
$('#mainPage').html() would give you the entire thing in a string "<div>
<div><ul><li>etc.</li></ul> </div> <div> <div><ul><li>etc.</li></ul> </div>"
$('#mainPage').children() would give you immidiate children [div,div]
$('#mainPage').find('.div') would giv =e you all the divs inside it [div,div,div,div]
if #mainPage is your main div, you can get of it's children by
var someVar = $('#mainPage').children();
Official api page
I think you're looking for jQuery detach method...
http://api.jquery.com/detach/
It will remove an element and store its contents, ready to be re-appended:
var a = p = $("a").detach()
If you only need the HTML you can save the HTML: var someVar = $("#mainPage").html(); and then append the HTML with the code you already have. Please tell me if I have misunderstood your question.

how to select 2nd <LI> element using javascript?

Using JavaScript, how can I dynamically change one of the list-items below from this:
<ul class="tabbernav">
<li class="tabberactive"><a title="All">All</a></li>
<li class=""><a title="One">One</a></li>
<li class=""><a title="Two">Two</a></li>
<li class=""><a title="Three">Three</a></li>
</ul>
to
<ul class="tabbernav">
<li class="tabberactive"><a title="All">All</a></li>
<li class=""><a title="One">One</a></li>
<li class=""><a title="Two">-----------NEW LIST ITEM CHANGED---------</a></li>
<li class=""><a title="Three">Three</a></li>
</ul>
I guess you could use getElementsByTagName inside of the ul to get all your list items inside an array. Then you can just edit the third element in your array, with index number 2.
var lItems = document.getElementsByTagName("ul").getElementsByTagName("li");
lItems[2].innerHTML = "<a title='Two'>----NEW LIST ITEM CHANGED-----</a>";
That will ofcourse get all ul elements on the page, and might lead to some strange results if you have more than two uls in your document. But you get the idea, right? Just ask some more if you don't understand what I'm trying to say.
Okay, the above code doesn't really work properly. I've modified my code a bit, but that also included a change in your HTML, as i presume you'll only have one ul "tabbernav", thus I changed it from class="tabbernav" to id="tabbernav". This is the code to do what you want.
var ul = document.getElementById("tabbernav");
var liArray = ul.getElementsByTagName("li");
for (var i = 0; i < liArray.length; i++) {
if(liArray[i].childNodes[0].title == "Two") {
liArray[i].innerHTML = "Your desired output";
}
}
Hope that helps you some more :)
I also suggest using jQuery, which makes selections like this trivial. In your case, you can use the :eq psuedo-selector to get the second line element:
$('.tabbernav li:eq(1)')
This selects the DOM element which is the second li (indexes start at 0) in an element with the class tabbernav. It returns a jQuery object which you can chain other methods to. Changing the inner HTML is done with .html('Your html here').
This is how you select the third Li element of your Ul list in pure JavaScript.
document.querySelectorAll("li")[2].innerHTML = "vasile";
Replace "Vasile" with your desired text.
var list = document.getElementsByTagName("li");
list[2].innerHTML = "<a title='Two'>------NEW LIST ITEM CHANGED----</a>";
this will work perfect
I know that this question is old but since it's still open, see how I modified the first answer. I feel someone else might need it.
>var lItems = document.getElementsByTagName("ul")[0];
>>var nth = lItems.getElementsByTagName("li")[2];
>>>nth.innerHTML = "<a title='Two'>----NEW LIST ITEM CHANGED-----> </a>";
So that basically solves it up by specifying the position of the lItems in particular to grab and in this case [0]. The code will not work properly if that position is missing because getElementsByTagName(NAME) returns a collection of html elements bearing that NAME specified. So that if you don't specify which among them all, the code fails.
If you like code reuse, see a function you can use for that. You just need to specify the parent element and its position and the childNode position and you get the same thing.
>var nthChild = function(parent, pos, childPos){
>>parent = document.getElementsByTagName(parent)[pos];
>>>return parent.children[childPos];
>>>>};
//used thus:
>nthChild("ul", 0, 2).innerHTML = "<a title='Two'>----NEW LIST ITEM CHANGED-----> </a>
";
How do you identify which <li> is the one you want to modify?
If you're doing it by index you could do something like this I think:
var list = document.getElementById("listid");
list.childNodes[2].innerHtml = "<a title='Two'>-----------NEW LIST ITEM CHANGED---------</a>";
Look into using a Javascript library such as JQuery. That will make your life a lot easier. Then you can do something like this:
$('li a[title=Two]').text('Changed Text Goes Here');
You'll need to check my syntax (not sure about the text() function), but it's easy enough to look up in JQuery's api docs.

Categories