How do I get all the LI UL elements ID value and place them in a JavaScript array? - javascript

I have to embed some tracking code on my site. So I have a list of LI elements with an ID value that I want to place inside an array of the snippet. They should be numeric like, 123, 456, etc inside an object. I want to do it in pure JavaScript.
This is my code I have tried. My HTML:
<ul id="itemGrid">
<li class="item" id="1080"> product code </li>
<li class="item" id="1487"> product code </li>
<li class="item" id="1488"> product code </li>
...
</ul>
This is the JavaScript code
// Get all LI items and get the ID of them in the object viewList
var catId = document.getElementById('itemGrid').getElementsByTagName('li');
window.criteo_q = window.criteo_q || [];
window.criteo_q.push(
// SHOULD BE LIKE THIS
// { event: "viewList", item: ["First item id", "Second item id", "Third item id"] }
// My actual code
{ event: "viewList", item: [ catId[].id ] }
);

try this
var lis = document.getElementById('itemGrid').getElementsByTagName('li');
var idArray = [];
for ( var counter = 0; counter < lis.length; counter++)
{
idArray.push( lis[ counter ].id );
}
console.log( idArray );

You can use querySelectorAll to select all the matching elements passed as selector.
The selector '#itemGrid li[id]' will select all the <li> elements inside #itemGrid element having id attribute on it.
The querySelectorAll returns a collection of HTML elements. Iterate over this collection to get the individual element id.
var lis = document.querySelectorAll('#itemGrid li[id]');
var arr = [];
for (var i = 0; i < lis.length; i++) {
arr.push(+lis[i].id);
}
console.log(arr);
document.write('<pre>' + JSON.stringify(arr, 0, 4) + '</pre>');
<ul id="itemGrid">
<li class="item" id="1080">1080</li>
<li class="item" id="1487">1487</li>
<li class="item" id="1488">1488</li>
</ul>
<hr />

You can convert your HTMLCollection to an Array by passing it through slice, and you can then map that array:
catId = Array.prototype.slice.call(catId).map(function(li) { return li.id; });
var catId = document.getElementById('itemGrid').getElementsByTagName('li');
catId = Array.prototype.slice.call(catId).map(function(li) { return li.id; });
document.write(catId);
<ul id="itemGrid">
<li class="item" id="1080"> product code </li>
<li class="item" id="1487"> product code </li>
<li class="item" id="1488"> product code </li>
</ul>

var lis = document.getElementById('itemGrid').getElementsByTagName('li');
var arr = [];
// You need to iterate the list lis
[].forEach.call( lis, function(el){
arr.push( el.id );
});
// Making the object you want
var criteo_q = { event: "viewList", item: arr };
console.log(criteo_q);
To iterate the list of DOM elements, you can also use

Related

Get id's retrieved by data attribute using javascript from li items

JavaScript
var sessions = [];
$('.rightDiv').each(function(index) {
var session = $.trim($(this).text().slice(0, -1)).split("×");
var sessionData = [];
for (var i = 0; i < session.length; i++) {
var ids = $(this).find('li').data('id');
var s = {
subjectOrder: i,
subjectID: ids
};
sessionData.push(s);
}
var ses = {
sessionNo: index,
sessionData: sessionData
};
sessions.push(ses);
});
HTML
<ul id="form_builder_sortable_sample" class="sortable rightDiv session4 ui-sortable">
<li class="draggable" data-id="1" name="Counting" >Counting<button onclick="deleteElement(event)" class="delbtn">×</button></li>
<li class="draggable" data-id="2" name="Priorities" >Priorities" class="delbtn">×</button></li>
</ul>
JSON
{"sessionNo":"0","sessionData":[{"subjectOrder":"0","subjectID":"1"},{"subjectOrder":"1","subjectID":"1"}]}
My Problem
What the code above does, is retrieves the session no from the ul class: class="sortable rightDiv session4" and each id of the li from data-id.
In this case it loops fine through the li items, but it only displays the id of the first li element.
It should be:
{"sessionNo":"0","sessionData":[{"subjectOrder":"0","subjectID":"1"},{"subjectOrder":"1","subjectID":"2"}]}
Any idea what's wrong?
Since you are using $(this).find('li').data('id');, it will always return the value of first li data attribute.
Use .each() to iterate and create an array
var sessionData = [];
$(this).find('li').each(function (index, elem) {
sessionData.push({
subjectOrder: index,
subjectID: $(elem).data('id')
});
})
change:
var ids = $(this).find('li').data('id');
to:
var ids = $(this).find('li').eq(i).data('id');

Convert list of HTML element into Javascript list of object

I'm trying to convert something like this HTML snippet:
<ul>
<li><span>Frank</span><img src="pic.jpg"></li>
<li><span>Steve</span><img src="pic2.jpg"></li>
</ul>
into a JavaScript objects that contain the name and the image's url. How can I do that?
Use map() method
var res = $('ul li').map(function() { // select all li and iterate
// return as required format of array elemnt
return {
name: $('span', this).text(), // get text in span
src: $('img', this).attr('src') // get src attribute
}
}).get(); // get array from jquery object
console.log(res);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li><span>Frank</span>
<img src="pic.jpg">
</li>
<li><span>Steve</span>
<img src="pic2.jpg">
</li>
</ul>
UPDATE : If you want to generate an object which has key as span text and value as src attribute then use each() method and iterate over elements and generate object.
var res = {};
$('ul li').each(function() { // select all li and iterate
res[$('span', this).text().trim()] = $('img', this).attr('src');
})
console.log(res);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li><span>Frank</span>
<img src="pic.jpg">
</li>
<li><span>Steve</span>
<img src="pic2.jpg">
</li>
</ul>
var objs = document.querySelectorAll('.to-js-obj li');
var objs_arr = [];
if (objs) {
for (var i = 0; i < objs.length; i++) {
var name = objs[i].querySelector('span').innerText;
var url = objs[i].querySelector('img').src;
objs_arr.push({
name: name,
src: url
});
}
console.log(JSON.stringify(objs_arr));
}
<ul class="to-js-obj">
<li><span>Frank</span>
<img src="pic.jpg">
</li>
<li><span>Steve</span>
<img src="pic2.jpg">
</li>
</ul>
Using jQuery
var $list = $('ul'), // get the list (ideally, add an ID)
$listItems = $list.find('li'); // find list items
if( $listItems.length > 0 ) { // if list items exist
var images = []; // create empty array to store objects
$.each( $listItems, function( index ) { // loop through the list items
var $item = $( $listItems[index] ); // save item as jQuery element
var name = $item.find('span').text(); // Get name from span
var imageSrc = $item.find('img').attr('src'); // Get img src
images[index] = {}; // Create new object in array
images[index].name = name; // Add name
images[index].imageSrc = imageSrc; // Add source
});
}
Returns
[Object {
imageSrc: "pic.jpg",
name: "Frank"
}, Object {
imageSrc: "pic2.jpg",
name: "Steve"
}]
You can use this:
var image_pairs = [];
$("ul li").each(function() {
image_pairs.push({
name: $(this).find("span").text(),
url: $(this).find("img").attr("src")
});
});
console.log(image_pairs);
<ul>
<li><span>Frank</span><img src="pic.jpg"></li>
<li><span>Steve</span><img src="pic2.jpg"></li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

How to convert html tree in to a customized json tree using jquery?

<ul id='parent_of_all'>
<li>
<span class='operator'>&&</span>
<ul>
<li>
<span class='operator'>||</span>
<ul>
<li>
<span class='operator'>&&</span>
<ul>
<li>
<span class='condition'>1 == 1</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li>
<span class='condition'>1 != 0</span>
</li>
</ul>
</li>
</ul>
to
{"&&":[{'||':[ {'&&':[ {"lhs": "1", "comparator": "==", "rhs":"1"} ]} ] } , {"lhs": "1", "comparator": "!=", "rhs":"0"}]}
As of now, I know the basics of jQuery, JavaScript. I need to know where to start thinking in order to accomplish the above conversion.
And the html tree could be more complex with more children.
You can do this with each and map
var obj = {}
var span = $('li > span').not('ul li span').text();
$('ul li span').each(function() {
var text = $(this).text().split(' ');
obj[span] = (obj[span]||[]).concat({lhs: text[0], comparator: text[1], rhs: text[2]});
});
console.log(obj)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<li>
<span>&&</span>
<ul>
<li>
<span>1 == 1</span>
</li>
</ul>
<ul>
<li>
<span>1 != 0</span>
</li>
</ul>
</li>
You will need a way to select the first level of li, I assumed you have a parent element with an id such as list. I wrote the following code using basic jquery so you can understand it.
var result = {};
var $all_li = $('#list').children('li'); // selecting the first level of li
for(var i in $all_li){ // iterating all_li using for (you may use forEach )
var $current_li = $( $all_li[i] ); // getting operator from first span
var operator = $current_li.children('span').html(); // the text of the operator
var $inner_spans = $current_li.find('>ul >li >span'); // getting list of children spans (from path $list>li>ul>li>span)
var li_spans = []; // an array where we will put the inner span objects
for(var j in $inner_spans){ // iterating the inner spans
var text = $($inner_spans[j]).html().split(" "); // splitting the html
li_spans.push({
lhs: text[0],
comparator: text[1],
rhs: text[2]
}); // adding the splitted html to an object. Note: error if text didn't have 2 white spaces
}
result[operator] = li_spans; // adding the operator key and li_spans value to the result json
}
This code will parse the html and construct the result json, it should work for the html format you provided. Keep in mind that it does not handle errors (such as bad tree format).
simmiar html formats.
Thanks #Alexandru and #Nenad for giving a start. I have been able to complete this on my own.
Below is the function that generates json.
function prepare_json(current_node){
var object = {}
var span = $(current_node).children('span')
if (span.hasClass('condition')){
var text = span.html().split(" ");
object = {lhs: text[0], comparator: text[1], rhs: text[2]}
}
else if(span.hasClass('operator')){
var operator = span.text()
object[operator] = (object[operator] || [])
var children = $(current_node).children('ul').children('li')
for(var i = 0; i < children.length; i++){
var child_pql = prepare_json([children[i]])
object[operator].push(child_pql)
}
}
return object
}
Below is the code that calls that function:
var parent_node = $('#parent_of_all').children('li')
var json = JSON.stringify(prepare_pql_json(parent_node), null, 2)

If submenu li has more than 5 li's create a new ul and place remaining list items?

I am basically trying to check if my submenu has more than five list items, and if it does grab the remaining list item's and place them inside a new ul that is outside of the current parent ul using jquery. it gets complicated because of the structure of the list.
Here is the DOM structure:
<ul id="nav" class="se test">
<li id="menu1" class="page-1307 parent-menu parent">
<div class="nav-inner">
<a class="menulink" id="menuitem1" onclick="return false" href="#">test<span class="toggle"></span></a>
<ul id="ie1" class="plain">
<li class="parent-menu parent">test<span class="toggle"></span>
<div class="submenu-wrapper">
<ul class="plain">
<li>test</li>
<li>test</li>
<li>test</li>
<li>test</li>
<li>test</li>
<li>test</li>
<li>test</li>
</ul>
</div>
</li>
<li class="parent-menu parent">test<span class="toggle"></span>
<div class="submenu-wrapper">
<ul class="plain">
<li>test</li>
<li>test</li>
<li>test</li>
<li>test</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li id="menu2" class="menulink page-7">
<div class="nav-inner">
test
</div>
</li>
</ul>
Basically i need to grab those remaining list items and place them in a new li.parent-menu.parent that includes the children div.sub-menu-wrapper and the ul.plain. the actual remaining list items would go inside the ul.plain of the new li.parent-menu. i hope thi makes since. i have been stuck on this for a day or two and unble to figure it out. any help would be greatly apprecitated, thank you.
This is what i am striving for, keep in mind it is dynamic.
you can:
Loop all ul in your document
foreach element count children
if found li number under an ul element is > 5
create a new list with the html of the required list
$(document).ready(function(){
$('.submenu-wrapper').each(function(){
var count_li=0;
var i=1;
$(this).children('ul').children('li').each(function(){
count_li++;
if(count_li>5 && i==1){
$(document.body).append('<ul id="newlist"></ul>');
$('#newlist').append($(this).nextUntil($(this).last()).andSelf());
i++;
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul id="nav" class="se test">
<li id="menu1" class="page-1307 parent-menu parent">
<div class="nav-inner">
<a class="menulink" id="menuitem1" onclick="return false" href="#">test<span class="toggle"></span></a>
<ul id="ie1" class="plain">
<li class="parent-menu parent">test<span class="toggle"></span>
<div class="submenu-wrapper">
<ul class="plain">
<li>test11</li>
<li>test12</li>
<li>test13</li>
<li>test14</li>
<li>test15</li>
<li>test16</li>
<li>test17</li>
</ul>
</div>
</li>
<li class="parent-menu parent">test<span class="toggle"></span>
<div class="submenu-wrapper">
<ul class="plain">
<li>test21</li>
<li>test22</li>
<li>test23</li>
<li>test24</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li id="menu2" class="menulink page-7">
<div class="nav-inner">
test
</div>
</li>
</ul>
Here is the final answer I was looking for:
megaMenu: function(){
function addNewList(current, newItems) {
var newList = $('<li class="parent-menu parent newLi">');
var div = $('<div class="submenu-wrapper">');
newList.append(div);
var ul = $('<ul class="plain">');
div.append(ul);
for (var i = 0; i < newItems.length; i++) {
ul.append(newItems[i]);
}
current.after(newList);
return newList;
}
function splitLists() {
var allLists = $(".plain > li.parent-menu");
for (var i = 0; i < allLists.length; i++) {
var currentList = $(allLists[i]);
var items = currentList.find("li");
if (items.length > 5) {
var temp = [];
for (var j = 5; j < items.length; j++) {
temp.push($(items[j]));
if (temp.length == 5) {
currentList = addNewList(currentList, temp);
temp = [];
}
}
if (temp.length > 0) {
currentList = addNewList(currentList, temp);
}
}
}
}
splitLists();
}
After some clarification via comments it seems you are looking for something like this. I have commented the code to explain the logic behind the process:
// function for adding a new LI item.
function addNewList(current, newItems) {
// Create the new li node.
var newList = $('<li class="parent-menu parent">');
// Add the initial a link.
newList.append('test<span class="toggle"></span>');
// Create and append the submenu-wrapper div to our new list item.
var div = $('<div class="submenu-wrapper">');
newList.append(div);
// Create and append the new ul node to our submenu-wrapper div.
var ul = $('<ul class="plain">');
div.append(ul);
// Loop the 5 (or less) items that have been specified and add them to our new list.
for (var i = 0; i < newItems.length; i++) {
// Using append will move the elements that already exist in the original place.
ul.append(newItems[i]);
}
// Add our new list item to the DOM.
current.after(newList);
return newList;
}
// Base function to split the lists as required.
function splitLists() {
// Get all the lists that we want to process.
var allLists = $(".plain > li.parent-menu");
// Loop each list and process.
for (var i = 0; i < allLists.length; i++) {
var currentList = $(allLists[i]);
// Get the sub-items that we need to split.
var items = currentList.find("li");
// We only care about lists that are more than 5 items.
if (items.length > 5) {
// Create array to store the items that we want to move (any after first 5)
var temp = [];
// Start at the 6th item an start moving them in blocks of 5.
for (var j = 5; j < items.length; j++) {
// Add the item to move to our temp array.
temp.push($(items[j]));
// If we have 5 in our temp array then move them to new list.
if (temp.length == 5) {
// Move items with helper function.
currentList = addNewList(currentList, temp);
// Clear the temp array ready for the next set of items.
temp = [];
}
}
// If we have any spare ones that didn't get handle in the length == 5 check, then process them now.
if (temp.length > 0) {
currentList = addNewList(currentList, temp);
}
}
}
}
// Run the process.
splitLists();
Here is a working example

Group list-items into sub-lists based on a data attribute

I want to append the <li> from one <ul> to another <ul> that's created on the fly. I want to group the list-items into new sub-lists based on their data-group attribute.
<ul id="sortable1">
<li data-group="A">test</li>
<li data-group="A">test1</li>
<li data-group="B">test2</li>
<li data-group="B">test3</li>
<li data-group="C">test4</li>
</ul>
Basically I'm trying to loop through this list and grap all <li> from each group, and then move it to another <ul>.
This is what I have so far, but I'm not getting the expected results. I have done this in Excel in the past but can't get it to work with jQuery.
var listItems = $("#sortable1").children("li");
listItems.each(function (idx, li) {
var product = $(li);
//grab current li
var str = $(this).text();
if (idx > 0) {
//append li
str += str;
if ($(this).data("group") != $(this).prev().data("group")) {
//I should be getting test and test1.
//but alert is only giving test1 test1.
alert(str);
//need to break into groups
//do something with groups
}
}
});
How about something like this:
$(function() {
var sortable = $("#sortable1"),
content = $("#content");
var groups = [];
sortable.find("li").each(function() {
var group = $(this).data("group");
if($.inArray(group, groups) === -1) {
groups.push(group);
}
});
groups.forEach(function(group) {
var liElements = sortable.find("li[data-group='" + group + "']"),
groupUl = $("<ul>").append(liElements);
content.append(groupUl);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="sortable1">
<li data-group="A">test</li>
<li data-group="A">test1</li>
<li data-group="B">test2</li>
<li data-group="B">test3</li>
<li data-group="C">test4</li>
</ul>
<div id="content">
</div>
I hope I didn't misunderstand you.

Categories