check for duplicate before appendChild - javascript

const pickNewUl = document.getElementById("ullist1");
var createLi = document.createElement("li");
createLi.id = listItems[i].id;
createLi.classList.add(pickNewUlsl);
createLi.innerHTML = listItems[i].textContent;
createLi.innerHTML += "<a onclick='remove(this)' class='removebtn'>X</a>";
pickNewUl.appendChild(createLi);
What I need to check in above code is: I want to check if there are any same id LI exists or not, if not then only it should append, otherwise it will not append.
pickNewUl is a UL list

You can find for any element inside element with .querySelectorAll as below.
if (pickNewUl.querySelectorAll('#' + listItems[i].id).length === 0) {
// Add element
}
Reference : https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
Your complete code should be like below.
const pickNewUl = document.getElementById("ullist1");
if (pickNewUl.querySelectorAll('#' + listItems[i].id).length === 0) {
var createLi = document.createElement("li");
createLi.id = listItems[i].id;
createLi.classList.add(pickNewUlsl);
createLi.innerHTML = listItems[i].textContent;
createLi.innerHTML += "<a onclick='remove(this)' class='removebtn'>X</a>";
pickNewUl.appendChild(createLi);
}

You can just wrap you code inside an if:
// the same as before but using pickNewUl instead of document
if (!pickNewUl.getElementById(listItems[i].id)) {
const createLi = document.createElement("li");
...
pickNewUl.appendChild(createLi);
}
Btw, I suggest to use a different approach excluding duplicated id:
// The string into querySelector method is a template string.
if (!pickNewUl.querySelector(`[data-item-id="${listItems[i].id}"]`)) {
const createLi = document.createElement("li");
createLi.dataset.itemId=listItems[i].id;
...
pickNewUl.appendChild(createLi);
}

Related

Create element inside another based on id

rigth now I have this code to draw some divs (based on some logic I'll have parent and childs.
array.forEach(async (a, b) => {
var currentDiv = 0;
let divHtml;
if (b === 0) {
//This should be the first parent
divHtml = document.createElement('div');
divHtml.id = 'someID' + currentDiv;
} else if (previousDiv != currentDiv) {
// This should be used for next parents based on the previousDiv & currentDiv logic
divHtml = document.createElement('div');
divHtml.id = 'someID' + currentDiv;
} else {
// This should be used only for childs. I want to create another div but inside the parent that I have stored into currentDiv.
divHtml = document.getElementById('someID' + currentDiv);
divHtml.id = 'someChildID' + currentDiv;
}
// Some more code below but what it's important is this (I continue using the divHtml in a lot of places on my code):
divHtml.setAttribute('someData', someDataAttribute);
});
So, my question is: if there is a way to get the parentDiv and draw inside the X childs elements and how can I do it? I tried with this:
divHtml = document.createElement('div').appendTo($('#someID' + currentDiv));
But I'm getting the .appendTo() is not a function error message.
.appendTo() is a jQuery method, it seems you are using plain javascript, maybe you want to use append or appendChild

Dynamically add li to ul javascript

I have an array of names and I want to show them on my page.
I created an empty ul in my html
<ul id="friendsList">
</ul>
And now I want to add the names to this ol but I doesn't work
for (var i = 0; i < names.length; i++) {
var name = names[i];
var li = document.createElement('li', name);
li.parentElement('friendsList');
}
Error:
Exception was thrown by user callback. TypeError: li.parentElement is not a function
You have to append your li to ul. This document.createElement('li', name); won't work.
Syntax
document.createElement(tagName[, options]);
tagName:
A string that specifies the type of element to be created.
options (Optional):
An optional ElementCreationOptions object containing a single property named is, whose value is the tag name for a custom element previously defined using customElements.define().
document.createElement() documentation
var names = ['John', 'Jane'];
var ul = document.getElementById("friendsList");
for (var i = 0; i < names.length; i++) {
var name = names[i];
var li = document.createElement('li');
li.appendChild(document.createTextNode(name));
ul.appendChild(li);
}
<ul id="friendsList">
</ul>
Node.parentElement is a read only property (ie if you want to inspect the parent node of a given node)
If you want to insert nodes there are different ways:
one of the solution is to use the method appendChild on the parent node.
If you want to avoid a reflow (the browser redraws the frame) one every insertion you can first insert your elements in a document fragment
const fragment = document.createDocumentFragment();
for(let name of names){
const li = document.createElement('li');
li.textContent = name;
fragment.appendChild(li);
}
//now you add all the nodes in once
const container = document.getElementById('friendsList');
container.appendChild(fragment);
Try below example - use appendChild on your UL, which you will get using getElementById():
var names = ["John","Mike","George"]
for (var i = 0; i < names.length; i++) {
var name = names[i];
var li = document.createElement('li');
li.innerHTML = name;
document.getElementById('friendsList').appendChild(li);
}
<ul id="friendsList"></ul>
// using Es6
let names = ['john','jane','smith'];
names.forEach((name)=>{
let li = document.createElement('li');
li.innerText = name;
document.getElementById('friendsList').appendChild(li);
})
<ul id="friendsList"></ul>
var friendsList = document.getElementById('friendsList');
var names = ["John","Mike","George"];
names.forEach(function (name) {
var li = document.createElement('li');
li.innerHTML = name;
friendsList.appendChild(li);
});

if statement inside jQuery selector

I'm getting those 2 vars from the DOM:
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
and I want here to find the classes in my DOM and show it
$('.filter-result').find('.'+get_category, '.'+get_subcategory ).show();
But I need to write it inside the .find() only if the variables are exist
I hope it answers your question:
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
var classes = [];
if (get_category) {
classes.push('.' + get_category);
}
if (get_subcategory) {
classes.push('.' + get_subcategory);
}
//if get_category or get_subcategory were found
if (classes.length) {
$('.filter-result').find(classes.join('')).show();
}
I do like Gabriels answer because it is very simple another option that works well and is extensible all you would have to do add another selector is add it to the selectors array. It is a little bit more advanced using javascripts filter and map array methods though.
var get_category = $('#category').find('.current').attr('rel');
var get_subcategory = $('#subcategory').find('.current').attr('rel');
var selectors = [get_category, get_subcategory];
var query = selectors.filter(function(elem) {
if (elem) { return elem };
}).map(function(elem){
return '.' + elem;
}).join(', ')
$('.filter-result').find(query).show();

jQuery append element if it doesn't exist, otherwise replace

Here's a short piece of code:
var $el = $("#something").find(".test");
if (!$el.length) {
$("#something").append('<div class="test">somecontent</div>');
} else {
$el.replaceWith('<div class="test">somenewcontent</div>');
}
I couldn't find a method appendOrReplaceWith or anything similar.
Any ideas how can I make it shorter?
I believe that:
$("#something").appendOrReplace('<div class="test">sometext</div>');
would be much easier to read, but no such method is available yet.
Just remove it first then append.
$(".test").remove();
$("#something").append('<div class="test">somecontent</div>');
Mandatory vanilla answer. It may not be shorter, but it's faster.
Get the element, grab all subelements with the class "test", create your div, check the subelements length, and if length is truthy, set the innerHTML to the div. Else, append it.
var el = document.getElementById("something");
var subel = el.getElementsByClassName("test");
var div = document.createElement("div");
div.className = "test"
if (subel.length) {
div.textContent = "somenewcontent";
while(el.hasChildNodes()) el.removeChild(el.lastChild); //remove child nodes
el.appendChild(div);
} else {
div.textContent = "somecontent";
el.appendChild(div);
}
Adding a method like findOrAppend to jQuery could be useful:
$.fn.findOrAppend = function(selector, content) {
var elements = this.find(selector);
return elements.length ? elements : $(content).appendTo(this);
}
Then you can chain text, replaceWith, empty etc. as needed:
$("#something")
.findOrAppend(".test", "<div class='test'>")
.text("newcontent");
First of all you should cache your selectors:
var $som = $('#something');
var $ele = $(".test",$som);
var newHtml = '<div class="test">somecontent</div>';
if (!$el[0]) $som.append( newHtml );
else $ele.replaceWith( newHtml );
but you already did it really fine, (beside not caching repeated selectors), and me, trying to make it smaller could be a**-kicked for not using {} for my if and else :)
I would do this
var $s = $("#something"), $t = $s.find(".test"), c = 'New content';
( $t[0] ? $t:$s)[( $t[0] ? 'html':'append')](( $t[0] ? c :$('<div>',{class:'test'}).append(c)));

Get list elements and its classes using jquery

I used $('#ul li').get() to get all the list elements and stored in an array, each of this list elements have classes...
var i;
var listClass = ('#ul li').get();
for(i=0;i<listClass.length;i++){
var theClass = listClass[i].attr("class"); //<--what's the proper function/method/code for this?
var content = listClass[i].innerHTML; //<-- works very well
//other codes here
}
How may i able to get the classes of each list elements...Thanks!
You can use jQuery's own map to do that:
alert($('#ul li').map(function() {
return this.className;
}).get());
http://jsfiddle.net/MhVU7/
for example. You can do anything with the returned array.
The reason the way you're doing it isn't working is because you're calling the non-existent method .attr on a native DOM element - it's not an extended jQuery object.
var lis = document.getElementById("ul").children;
for (var i = 0, len = lis.length; i < len; i++) {
var li = lis[i],
className = li.className,
value = li.value,
text = li.textContent;
// code
}
The get() method returns a native array of DOM elements, not a jQuery object.
You should use jQuery:
var lists = $('ul li');
var className = lists.eq(i).attr('class');
var content = lists.eq(i).text();
If you want to loop through all the elements
$('ul li').each(function(){
var className = $(this).attr('class');
var content = $(this).text();
});
I have commented the code to better help you understand it.
$("#ul li").each(function() { /* you should only be using # selector to identify id's - if it's all ul's you want just put ul. */
var klass = this.className; /* this refers to the native DOM object, which contains className */
var textContents = this.innerText || this.textContent; /* the text of the list, does not include html tags */
var childNodes = this.childNodes; /* the child nodes of the list, each unencased string of text will be converted into a TextNode */
console.log(klass + ' ' + textContents); /* replace console.log with alert if you do not have a console */
console.log(childNodes);
});
here is an example of the above.
Good Luck!

Categories

Resources