how to build a dynamic menu using jquery? - javascript

I try to create a dynamic menu using jquery:
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
main.append("<li>");
$('li').append("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + "</span></a>");
main.append("</li>");
}
}
The menu is created, but in each li i get more than one span, there is an "inside" loop (I think...)
createing more spans than needed... how can i solve/control it so each li gets
one span according to the for - loop index ?

You are seeing that behaviour because you are appending that anchor with span in selecting all the li elements.
Try,
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
var xLi =("<li>").appendTo(main);
xLi.append("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + "</span></a>");
main.append(xLi);
}
}

you can do it simply as below
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
main.append($("<li>").append("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + "</span></a>"));
}
}

$('li') this selector will get every li on the html so every time you iterate to create a new li element you gonna add a new span to all of them.
Try like this:
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
var menuLine = $('<li>');
menuLine.html("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + " </span></a>" );
main.append(menuLine);
}
}

Related

How to create loop to add eventListener for each item in a list

Wracking my brains on this one but I'm sure it's just my inexperience with js.
I have a list of items and I am trying to create an eventListener for each item row so when I mouseover the row some icons will appear. The icons should hide again on mouseout.
I am using setAttribute to change the opacity of the elements on mouseover and mouseout events.
My problem is after the loop runs to create the eventListeners the setAttribute only affects the very last row of the loop - regardless of which row I mouse over.
I have a JSFiddle here which shows you the exact behaviour (better than I can explain): https://jsfiddle.net/Finno/ds9q7zju/27/
Note: this is a simplified example but it exhibits the same behaviour. My real app has the items formatted in a drop down menu.
Here is the code :
var total = 8;
var items;
var row;
var sort;
var trash;
for (var i = 0; i < total; i++) {
items = items + '<div id="row' + i + '">';
items = items + '<span class="hidden" id="sort' + i + '">SORT</span>';
items = items + '<span id="content' + i + '">Some content</span>';
items = items + '<span class="hidden" id="trash' + i + '">TRASH</span>';
items = items + '</div><br>';
}
document.getElementById("queue").innerHTML = items;
for (var i = 0; i < total; i++) {
row = 'row' + i;
sort = 'sort' + i;
trash = 'trash' + i;
document.getElementById(row).addEventListener("mouseover", function() {
document.getElementById(sort).setAttribute("style", "opacity:1 !important");
document.getElementById(trash).setAttribute("style", "opacity:1 !important");
});
document.getElementById(row).addEventListener("mouseout", function() {
document.getElementById(sort).setAttribute("style", "opacity:0 !important");
document.getElementById(trash).setAttribute("style", "opacity:0 !important");
});
}
You need to recreate the variables in each iteration, Try this,
Also, you can use string interpolation in place of + to join strings
var total = 8;
var items;
for (var i = 0; i < total; i++) {
items = items + '<div id="row' + i + '">';
items = items + '<span class="hidden" id="sort' + i + '">SORT</span>';
items = items + '<span id="content' + i + '">Some content</span>';
items = items + '<span class="hidden" id="trash' + i + '">TRASH</span>';
items = items + '</div><br>';
}
document.getElementById("queue").innerHTML = items;
for (var i = 0; i < total; i++) {
let row = 'row' + i;
let sort = 'sort' + i;
let trash = 'trash' + i;
document.getElementById(row).addEventListener("mouseover", function() {
document.getElementById(sort).setAttribute("style", "opacity:1 !important");
document.getElementById(trash).setAttribute("style", "opacity:1 !important");
});
document.getElementById(row).addEventListener("mouseout", function() {
document.getElementById(sort).setAttribute("style", "opacity:0 !important");
document.getElementById(trash).setAttribute("style", "opacity:0 !important");
});
}

Getting undefined when trying to fetch an ID from a data attribute

I can't figure out why am I getting undefined when trying to console.outthe iUsedId variable from the code below.
Here I attatch the user id to data-iUserId.
var aUsers = [];
for( var i = 0; i < aUsers.length; i++ ){
$("#lblUsers").append('<tr><th scope="row">'+aUsers[i].id+'</th><td>'+aUsers[i].username+'</td><td>'+aUsers[i].firstName+'</td><td>'+aUsers[i].lastName+'</td><td>'+aUsers[i].email+'</td><td>'+"<span data-iUserId='"+aUsers[i].id+"'</span><input type='checkbox' id='chk_"+i+"'"+'</td></tr>');
}
And here I am trying to use the data from the data attribute, but in the console all I get is undefined.
$(document).ready(function() {
$("#remove").on("click", function() {
$('input:checked').each(function() {
$(this).closest('tr').remove();
var iUserId = $(this).attr('data-iUserId');
console.log(iUserId);
for (var i = 0; i < aUsers.length; i++) {
if (iUserId == aUsers[i].iUsersId) {
aUsers.splice(i, 1);
}
}
});
});
});
Any gueses? Please help!
You are deleting the parent with the containers, then trying to access the element.
removing the parent should be in the last step:
$(document).ready(function() {
$("#remove").on("click", function() {
$('input:checked').each(function() {
var iUserId = $(this).closest('span').attr('data-iUserId');
console.log(iUserId);
for (var i = 0; i < aUsers.length; i++) {
if (iUserId == aUsers[i].iUsersId) {
aUsers.splice(i, 1);
}
}
$(this).closest('tr').remove();
});
});
});
Also, consider the comment of #pBuch
The reason is you are looping over the checkboxes and not the span's which have the attribute you are trying to access.
$(this) refers to the checkbox and not the span in the each method you are using:
$('input:checked').each(function() {
// Inside this each statement $(this) refers
// to the the current 'input:checked' element being accessed
});
You should put the data-iUserId attribute on the checkbox since you are accessing that element.
Also! You are missing the closing '>' on the opening span tag:
<span data-iUserId='"+aUsers[i].id+"'</span>
var aUsers = [];
//...somehow populate array...
// We have to assume here that the array got populated
for (var i = 0; i < aUsers.length; i++) {
$("#lblUsers").append('<tr><th scope="row">' + aUsers[i].id + '</th><td>' + aUsers[i].username + '</td><td>' + aUsers[i].firstName + '</td><td>' + aUsers[i].lastName + '</td><td>' + aUsers[i].email + '</td><td>' + "<span data-iUserId='" + aUsers[i].id + "'></span><input type='checkbox' id='chk_" + i + "'" + '</td></tr>');
}
$(document).ready(function() {
$("#remove").on("click", function() {
$("#lblUsers").find('input[type="checkbox"]:checked').each(function() {
// fixed to get the element with the data
var iUserId = $(this).siblings('[data-iUserId]').data('iuserid');
console.log(iUserId);
for (var i = 0; i < aUsers.length; i++) {
// bad practice to use a global aUsers
if (iUserId == aUsers[i].iUsersId) {
aUsers.splice(i, 1);
}
}
$(this).closest('tr').remove();
});
});
});

Pure JS Add class in many divs of the same id

I want to add class " hidden" in many divs of the same id.
function show_wzorce(x) {
document.getElementById("" + x + "").className += " hidden";
var divs = document.getElementById("" + x + "");
for (var i = 0; i < divs.length; i++) {
divs[i].className += " hidden";
}
}
ID has to be unique. You can do the same thing but with getElementsByClassName (there is a "s" after element)
Your code should look something like this:
function show_wzorce(x) { // assuming x is string
var divs = document.getElementsByClassName(x); //this returns an HTML Collection. But works as an array
for (var i = 0; i < divs.length; i++) {
divs[i].className += " hidden";
}
}

change class if value greater then defined value

I want to change the class of an element depending on the value. Is it possible to do this inside the loop?
Javascript:
$.post(url, filteredObject, function (data2) {
for (i = 0; i < 7; i++) {
$('#ty' + (i + 1).toString()).text(numberWithCommas(data2[i].TY));
$('#sdly' + (i + 1).toString()).text(numberWithCommas(data2[i].SDLY));
$('#fcst' + (i + 1).toString()).text(numberWithCommas(data2[i].FCSTYTD));
}
});
I tried something like this but didn't work.
var textvalue = parseInt($('#ty' + (i + 1).toString()).text)
if (textvalue < 0) {
$('#ty' + (i + 1).toString()).toggleClass("fa fa-level-down");
}
else {
$('#ty' + (i + 1).toString()).toggleClass("fa fa-level-up");
}
Can anyone help me.
you should not use "toggleClass"
.toggleClass( className )
Description: Add or remove one or more classes from each element in the set of matched elements, depending on either the class's presence [...]
it removes the class if it is present and adds it if it is not, so achieve that you only have one of fa-level-down and fa-level-up you should use .addClass( className ) and .removeClass( className )
var textvalue = parseInt($('#ty' + (i + 1).toString()).text)
if (textvalue < 0) {
$('#ty' + (i + 1).toString()).addClass("fa-level-down");
$('#ty' + (i + 1).toString()).removeClass("fa-level-up");
}
else {
$('#ty' + (i + 1).toString()).addClass("fa-level-up");
$('#ty' + (i + 1).toString()).removeClass("fa-level-down");
}
You are missing brackets after .text on the line:
var textvalue = parseInt($('#ty' + (i + 1).toString()).text)
You should use .text() to get the text of a jQuery object.
var textvalue = parseInt($('#ty' + (i + 1).toString()).text())

Add javascript condition inside text variable

I have code working fine but I wanna simplify:
<script type="text/javascript">
function RenderPager(items) {
for (var i = 0; i < items.length; i++) {
var li = "<li";
if(i == 0){
li += " class='first'";
}
li +=">" + i + "</li>";
// do something else
}
}
</script>
I would like to have condition inline something like this:
for (var i = 0; i < items.length; i++) {
var li = "<li" + if(i == 0){ li += " class='first'" }; + ">" + i + "</li>";
// do something else
}
But this is not working and I tried everything but I don't know how to combine javascript condition in text variable. Is it possible?
You can use the conditional operator (?..:), also known as the ternary operator:
var li = "<li" + (i == 0 ? " class='first'" : "") + ">" + i + "</li>";
Also note, this could probably also be done using a little CSS with the :fist-child pseudo-class, but it's not supported by older versions of IE. See this compatibility chart:
li:first-child {
/* applies only to the first <li> element in a list */
}

Categories