Get data from HTML list to array - javascript

I'm using SortableJS and have a nested sortable list.
<ul id="nestedDemo" class="nested-sortable">
<li data-id="11">Item 1.1
<ul class="nested-sortable">
<li data-id="21">Item 2.1</li>
<li data-id="22">Item 2.2
<ul class="nested-sortable">
<li data-id="32">Item 3.2</li>
<li data-id="33">Item 3.3</li>
<li data-id="34">Item 3.4</li>
</ul>
</li>
<li data-id="23">Item 2.3</li>
<li data-id="31">Item 3.1</li>
<li data-id="24">Item 2.4</li>
</ul>
</li>
<li data-id="12">Item 1.2</li>
<li data-id="13">Item 1.3</li>
<li data-id="14">Item 1.4
<ul class="nested-sortable">
<li data-id="21">Item 2.1</li>
<li data-id="22">Item 2.2</li>
<li data-id="23">Item 2.3</li>
<li data-id="24">Item 2.4</li>
</ul>
</li>
<li data-id="15">Item 1.5</li>
</ul>
With the following script I get an JSON string with each that changed.
var nestedSortables = [].slice.call(document.querySelectorAll('.nested-sortable'));
for( var i = 0; i < nestedSortables.length; i++ )
{
new Sortable( nestedSortables[i], {
group: 'nested',
dataIdAttr: 'data-id',
fallbackOnBody: true,
swapThreshold: 0.65,
store: {
set: function (evt) {
var order = evt.toArray();
console.log("Order: "+ JSON.stringify( order ) );
}
}
});
}
The problem is that I need the whole tree as an JSON string or array to store it and not only the values of the that have changes in.
How can I get an array with the whole tree?

You could store all nested sortables inside an array, and then get the order from each of them on set.
var nestedSortables = [].slice.call(document.querySelectorAll('.nested-sortable'));
// ARRAY TO STORE ALL NESTED SORTABLES
const sortables = []
for (var i = 0; i < nestedSortables.length; i++) {
var sortable = Sortable.create(nestedSortables[i], {
group: 'nested',
dataIdAttr: 'data-id',
fallbackOnBody: true,
swapThreshold: 0.65,
store: {
set: function(sortable) {
// ITERATE EACH NESTED SORTABLE IN OUR ARRAY
for (let s of sortables) {
// GET THE ORDER OF THIS SORTABLE
let order = s.toArray();
console.log(order.join('|'));
}
}
}
});
// PUSH THE NEW SORTABLE IN OUR ARRAY
sortables.push(sortable)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js"></script>
<ul id="nestedDemo" class="nested-sortable">
<li data-id="11">Item 1.1
<ul class="nested-sortable">
<li data-id="21">Item 2.1</li>
<li data-id="22">Item 2.2
<ul class="nested-sortable">
<li data-id="32">Item 3.2</li>
<li data-id="33">Item 3.3</li>
<li data-id="34">Item 3.4</li>
</ul>
</li>
<li data-id="23">Item 2.3</li>
<li data-id="31">Item 3.1</li>
<li data-id="24">Item 2.4</li>
</ul>
</li>
<li data-id="12">Item 1.2</li>
<li data-id="13">Item 1.3</li>
<li data-id="14">Item 1.4
<ul class="nested-sortable">
<li data-id="21">Item 2.1</li>
<li data-id="22">Item 2.2</li>
<li data-id="23">Item 2.3</li>
<li data-id="24">Item 2.4</li>
</ul>
</li>
<li data-id="15">Item 1.5</li>
</ul>

Related

How to filter multiple id at textarea and display none other unrelate

i want to find user_id from all list data.
when i search user_id, i will copy user_id from excel and paste it into textarea.
and then the all user_id that i chosen must match the user_id from all list data.
this's my code
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea name="" id="paste_your_id"></textarea>
<ul class="ul-list">
<li data-id="1">Mr. A</li>
<li data-id="2">Mr. B</li>
<li data-id="3">Mr. C</li>
<li data-id="4">Mr. D</li>
<li data-id="5">Mr. E</li>
<li data-id="6">Mr. F</li>
<li data-id="7">Mr. G</li>
</ul>
output
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea name="" id="paste_your_id">1
2
3
7</textarea>
<ul class="ul-list">
<li data-id="1">Mr. A</li>
<li data-id="2">Mr. B</li>
<li data-id="3">Mr. C</li>
<li data-id="4" style="display:none;">Mr. D</li>
<li data-id="5" style="display:none;">Mr. E</li>
<li data-id="6" style="display:none;">Mr. F</li>
<li data-id="7" >Mr. G</li>
</ul>
Thank you so much
You can achieve it by this simple way
var userList = $(".ul-list").find("li").toArray(); // Store list of userId value here
$("#paste_your_id").on("keyup", function()
{
var strIds = $(this).val();
var arrayIds = strIds.split(/[^\d]+/); // Split each item by `whitespace` or `by line`
var isFilter = arrayIds.filter(item => item !== "").length > 0;
userList.forEach(item =>
{
var id = $(item).data("id").toString();
var isShow = !isFilter || arrayIds.indexOf(id) !== -1;
$(item).toggle(isShow);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea name="" id="paste_your_id"></textarea>
<ul class="ul-list">
<li data-id="1">Mr. A</li>
<li data-id="2">Mr. B</li>
<li data-id="3">Mr. C</li>
<li data-id="4">Mr. D</li>
<li data-id="5">Mr. E</li>
<li data-id="6">Mr. F</li>
<li data-id="7">Mr. G</li>
</ul>
Updated
Your list data can revert to display:block when you delete text in textarea by this way
var isFilter = arrayIds.filter(item => item !== "").length > 0;
Use .toggle() to be more elegant
Some comments that I mentioned in JS code to get more performance.
Your JS code
var arrEleIds = $("li").map(function(){return $(this).attr("data-id");}).get();
var arrTextVal = $('#paste_your_id').val().replace(/\n/ig, '').split("");
var difference = arrEleIds .filter(x => !arrTextVal.includes(x));
difference.forEach(item =>
{
$('li[data-id='+item+']').hide();
})
Your HTML
<textarea name="" id="paste_your_id">1
2
3
7</textarea>
<ul class="ul-list">
<li data-id="1">Mr. A</li>
<li data-id="2">Mr. B</li>
<li data-id="3">Mr. C</li>
<li data-id="4">Mr. D</li>
<li data-id="5">Mr. E</li>
<li data-id="6">Mr. F</li>
<li data-id="7">Mr. G</li>
</ul>
or this...
const regex = /[A-Za-z0-9]+/g // accept chars and nums
, Id_Elm = document.getElementById('paste_your_id')
, li_List = document.querySelectorAll('ul.ul-list li')
;
function Set_List() {
let IDs = Id_Elm.value.match(regex) || []
li_List.forEach(li=>{
li.style.display = (IDs.includes( li.dataset.id )) ? 'list-item' : 'none'
})
}
Set_List()
Id_Elm.oninput = Set_List
<textarea name="" id="paste_your_id"></textarea>
<ul class="ul-list">
<li data-id="1">Mr. A</li>
<li data-id="2">Mr. B</li>
<li data-id="3">Mr. C</li>
<li data-id="4">Mr. D</li>
<li data-id="5">Mr. E</li>
<li data-id="6">Mr. F</li>
<li data-id="7">Mr. G</li>
</ul>

JavaScript or jQuery compare two ordered lists using data-attribute

I want to be able to compare two lists using data attribute in either Javascript or jQuery. I can't find an example of this anywhere and don't know how to go about it.
The first list is static and the second list is sortable. Once the user sorts the lists in the right order, [data-compare 1 to 4] in both lists, they click a button to check if they got the matches correct.
There are examples of setting the correct order 1 to X in a single list, but, none I can find to compare two lists.
The basic HTML:
<ul>
<li data-compare="1">Bananas</li>
<li data-compare="2">tomatoes</li>
<li data-compare="3">carrots</li>
<li data-compare="4">dates</li>
</ul>
<ul>
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>
If an ordered list has data-compare attributes with the values 1, 2, 3, 4, you can just check if the the value of the data-compare is identical to the list item's index + 1:
function checkOrdered(list) {
return Array.from(list).every((item, i) => item.getAttribute('data-compare') == (i + 1));
}
console.log(checkOrdered(document.querySelectorAll('#list1 > li')));
console.log(checkOrdered(document.querySelectorAll('#list2 > li')));
<ul id="list1">
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>
<ul id="list2">
<li data-compare="1">Tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
<li data-compare="4">Palm tree</li>
</ul>
You can do the same thing using another list as the compare basis:
function checkOrdered(list1, list2) {
return Array.from(list1).every((item, i) =>
item.getAttribute('data-compare') === list2[i].getAttribute('data-compare'));
}
const src = document.querySelectorAll('#src > li');
const target1 = document.querySelectorAll('#target1 > li');
const target2 = document.querySelectorAll('#target2 > li');
console.log(checkOrdered(src, target1));
console.log(checkOrdered(src, target2));
<ul id="src">
<li data-compare="1">Bananas</li>
<li data-compare="2">tomatoes</li>
<li data-compare="3">carrots</li>
<li data-compare="4">dates</li>
</ul>
<ul id="target1">
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>
<ul id="target2">
<li data-compare="1">Tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
<li data-compare="4">Palm tree</li>
</ul>
You can first get two arrays with data-compare values and then use every method to check if each element is the same in both arrays.
const getData = arr => {
return arr.map(function() {
return $(this).attr('data-compare')
}).get();
}
const l1 = getData($('ul:nth-of-type(1) li'))
const l2 = getData($('ul:nth-of-type(2) li'))
const check = l1.every((e, i) => l2[i] == e);
console.log(check)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li data-compare="1">Bananas</li>
<li data-compare="2">tomatoes</li>
<li data-compare="3">carrots</li>
<li data-compare="4">dates</li>
</ul>
<ul>
<li data-compare="1">Tree</li>
<li data-compare="4">Palm tree</li>
<li data-compare="2">Bush</li>
<li data-compare="3">In the ground</li>
</ul>

jQuery - Expand Tree View up to selected node level

I am trying to expand the tree view up to selected node level. But I am not getting any idea about this please can any one help me on this.
For example We clicked on 'Parent d' in 'Category list' then expand 'Tree View List' up to 'Parent d' level for more details check Here
HTML
<h3>
Category list
</h3>
When click on any li expand tree list up to selected level
<ul id='category'>
<li li-id='1' id='1'>Parent 1</li>
<li li-id='2' id='2'>Parent 2</li>
<li li-id='3' id='3'>Parent 3</li>
<li li-id='4' id='4'>Parent 4</li>
<li li-id='5' id='5'>Parent c</li>
<li li-id='6' id='6'>Parent d</li>
<li li-id='7' id='7'>Parent a</li>
<li li-id='8' id='8'>Parent b</li>
<li li-id='9' id='9'>Parent e</li>
<li parent-id='5' li-id='10'>Parent x</li>
</ul>
Tree View List
<h3>
Node View
</h3>
<div class='tree'>
<ul id='ulCollapse'>
<li parent-id='0' li-id='1'>Parent 1</li>
<li parent-id='1' li-id='2'>Parent 2</li>
<li parent-id='1' li-id='3'>Parent 3</li>
<li parent-id='1' li-id='4'>Parent 4</li>
<li parent-id='3' li-id='5'>Parent c</li>
<li parent-id='3' li-id='6'>Parent d</li>
<li parent-id='2' li-id='7'>Parent a</li>
<li parent-id='4' li-id='8'>Parent b</li>
<li parent-id='4' li-id='9'>Parent e</li>
<li parent-id='5' li-id='10'>Parent x</li>
</ul>
</div>
jQuery
//$('#ulCollapse li').hide();
$('ul li').click(function(){
var nodeId = $(this).attr('li-id');
alert(nodeId);
})
var $ul = $('ul');
$ul.find('li[parent-id]').each(function() {
$ul.find('li[parent-id=' + $(this).attr('li-id') + ']')
.wrapAll('<ul />')
.parent()
.appendTo(this)
});
DEMO
I am not a javascript developer but, tried to solve your problem, here is the working demo
var $ul = $('ul');
$(document).ready(function() {
$ul.find('li[parent-id]').each(function() {
$ul.find('li[parent-id=' + $(this).attr('li-id') + ']').wrapAll('<ul />').parent().appendTo(this)
// not changed its your code still, but I need this only first time, so moved into document ready
});
});
$('ul#category li').click(function() {
$("#ulCollapse1").html(''); // I have created a new div section
$("ul").removeAttr('class'); // remove active classes
var nodeId = $(this).attr('id');
arrangeNodes(nodeId);
$("#ulCollapse1").html($(".active").parent().clone()); //get the marked elements first parent (which is 'li')
$("#ulCollapse").hide(); // hide the main treeview
});
function arrangeNodes(item) {
$ul.find('li[parent-id=' + item + ']').parent().closest("ul").addClass("active"); // find item and mark the first ul as active (selected)
}
Hope helps,
I don't fully understand what you're trying to achieve.
But maybe :lt() is what you're looking for
HTML
<h3>
Category list
</h3>
<ul id='category'>
<li li-id='1' id='1'>Parent 1</li>
<li li-id='2' id='2'>Parent 2</li>
<li li-id='3' id='3'>Parent 3</li>
<li li-id='4' id='4'>Parent 4</li>
<li li-id='5' id='5'>Parent c</li>
<li li-id='6' id='6'>Parent d</li>
<li li-id='7' id='7'>Parent a</li>
<li li-id='8' id='8'>Parent b</li>
<li li-id='9' id='9'>Parent e</li>
<li li-id='10' id='10'>Parent x</li>
</ul>
<br>
<br>
<h3>
Node View
</h3>
<div class='tree'>
<ul id='ulCollapse'>
<li parent-id='1'>
<ul>
<li>Parent 1</li>
</ul>
</li>
<li parent-id='2'>
<ul>
<li>Parent 2</li>
<li>Parent 3</li>
<li>Parent 4</li>
</ul>
</li>
<li parent-id='3'>
<ul>
<li>Parent c</li>
<li>Parent d</li>
<li>Parent a</li>
</ul>
</li>
<li parent-id='4'>
<ul>
<li>Parent b</li>
<li>Parent e</li>
</ul>
</li>
<li parent-id='5'>
<ul>
<li>Parent x</li>
</ul>
</li>
</ul>
</div>
JS
$cats = $("#category");
$tree = $("#ulCollapse");
$tree.children().hide();
$cats.on("click", "li", function() {
var nodeId = $(this).attr('li-id');
console.info("NODE ID: ", nodeId);
$tree.children().hide();
var maxEq = $tree.children("[parent-id='" + nodeId + "']").index();
maxEq < 0 && (maxEq = 0);
maxEq++; //LTE since :lte() doesn't exist
console.info("MAX EQ: ", maxEq);
$tree.children(":lt(" + maxEq + ")").show();
});
FIDDLE ==> https://jsfiddle.net/x45j4fx6/1/

Onclick convert UL to JSON

On my webpage I have an area that summarizes multiple stores. Each store is a list with multiple list items.
<div id="dealersList" class="dealer-summary">
<ul class="dealer-summary-list">
<li class="dealerName">Brecksville</li>
<li class="dealer-summary-listItem">8383 Chippewa Rd.,</li>
<li class="dealer-summary-listItem">Brecksville, Ohio - 44141</li>
<li class="dealer-summary-listItem">(440) 740-0535</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Dayton</li>
<li class="dealer-summary-listItem">3520 W Siebenthaler Ave.,</li>
<li class="dealer-summary-listItem">Dayton, Ohio - 45406</li>
<li class="dealer-summary-listItem">(937) 567-9578</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Cleveland</li>
<li class="dealer-summary-listItem">900 Euclid Ave.,</li>
<li class="dealer-summary-listItem">Cleveland, Ohio - 44115</li>
<li class="dealer-summary-listItem">(216) 302-3020</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Bridgetown</li>
<li class="dealer-summary-listItem">5830 Harrison Ave.,</li>
<li class="dealer-summary-listItem">Cincinnati, Ohio - 45248</li>
<li class="dealer-summary-listItem">(513) 574-2810</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Columbus</li>
<li class="dealer-summary-listItem">1350 N High St.,</li>
<li class="dealer-summary-listItem">Columbus, Ohio - 43201</li>
<li class="dealer-summary-listItem">(614) 294-2545</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Toledo</li>
<li class="dealer-summary-listItem">1415 S Byrne Rd.,</li>
<li class="dealer-summary-listItem">Toledo, Ohio - 43614</li>
<li class="dealer-summary-listItem">(419) 382-0792</li>
</ul>
</div>
</div>
I would like to click any List and have it converted to a JSON similar to this
Object
address:"8383 Chippewa Rd.,"
locale:"Brecksville, Ohio - 44141"
phone:"(440) 740-0535"
title:"Brecksville"
I've tried multiple times with incorrect results...
var dealerSummary = [];
$("ul.dealer-summary-list > li").each(function () {
dealerSummary.push({
"title": $(this).text(),
"address": $(this).text(),
"locale": $(this).text(),
"phone":$(this).text()
});
})
Only the clicked item should be converted. Please help.
Assuming your li tags are always in the same order: title, address, locale, phone, you can do this with a simple find() and then concatenate the text of the li into an object.
Here's an example:
$("#dealersList").on("click", "ul", function() {
var obj = {};
var items = $(this).find("li");
obj.title = items.eq(0).text();
obj.address = items.eq(1).text();
obj.locale = items.eq(2).text();
obj.phone = items.eq(3).text();
console.log(obj);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="dealersList" class="dealer-summary">
<ul class="dealer-summary-list">
<li class="dealerName">Brecksville</li>
<li class="dealer-summary-listItem">8383 Chippewa Rd.,</li>
<li class="dealer-summary-listItem">Brecksville, Ohio - 44141</li>
<li class="dealer-summary-listItem">(440) 740-0535</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Dayton</li>
<li class="dealer-summary-listItem">3520 W Siebenthaler Ave.,</li>
<li class="dealer-summary-listItem">Dayton, Ohio - 45406</li>
<li class="dealer-summary-listItem">(937) 567-9578</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Cleveland</li>
<li class="dealer-summary-listItem">900 Euclid Ave.,</li>
<li class="dealer-summary-listItem">Cleveland, Ohio - 44115</li>
<li class="dealer-summary-listItem">(216) 302-3020</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Bridgetown</li>
<li class="dealer-summary-listItem">5830 Harrison Ave.,</li>
<li class="dealer-summary-listItem">Cincinnati, Ohio - 45248</li>
<li class="dealer-summary-listItem">(513) 574-2810</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Columbus</li>
<li class="dealer-summary-listItem">1350 N High St.,</li>
<li class="dealer-summary-listItem">Columbus, Ohio - 43201</li>
<li class="dealer-summary-listItem">(614) 294-2545</li>
</ul>
<ul class="dealer-summary-list">
<li class="dealerName">Toledo</li>
<li class="dealer-summary-listItem">1415 S Byrne Rd.,</li>
<li class="dealer-summary-listItem">Toledo, Ohio - 43614</li>
<li class="dealer-summary-listItem">(419) 382-0792</li>
</ul>
</div>
You can add event listeners on all the ul and then just create an object with the desired properties assuming li order doesn't change.
var uls = document.querySelectorAll('.dealer-summary-list');
var obj = {};
uls.forEach(function(ul){
ul.addEventListener('click', function(){
var lis = ul.querySelectorAll('li');
obj.address = lis[1].innerText;
obj.locale = lis[2].innerText;
obj.phone = lis[3].innerText;
obj.title = lis[0].innerText;
console.log(JSON.stringify(obj));
});
});

Convert dynamic DOM structure to JSON

How can convert below DOM to JSON array which will have many more leafs in thefuture . I have tried a lot but didn't got any solution. I found this but it is not possible in my case.
HTML Code
<ul id="org1">
<li>
Main
<ul data-self="1">
<li data-self="2" data-parent="1">A
<ul data-self="2">
<li data-self="5" data-parent="2">A1</li>
<li data-self="6" data-parent="2">A2</li>
<li data-self="7" data-parent="2">A3</li>
<li data-self="8" data-parent="2">A4</li>
<li data-self="9" data-parent="2">A5</li>
<li data-self="10" data-parent="2">A6</li>
</ul>
</li>
<li data-self="3" data-parent="1">B
<ul data-self="3">
<li data-self="11" data-parent="3">B1</li>
<li data-self="12" data-parent="3">B2</li>
<li data-self="13" data-parent="3">B3</li>
<li data-self="14" data-parent="3">B4</li>
</ul>
</li>
</ul>
</li>
</ul>
JSON Required is
{
1:{
2:{5,6,7,8,9,10},
3:{11,12,13,14}
}
}
Script
function recursive(dis)
{
$(this).find(' > ul ').each(function(){
params[$(this).attr('data-self')]=[];
var i=0;
$(this).find('li').each(function(){
if($(this).has('ul'))
{
params[$(this).attr('data-parent')][i++]=rec(this);
}else
{
params[$(this).attr('data-parent')][i++]=$(this).attr('data-self');
}
});
});
}
recursive('#org1');
console.log(params);
I would prefer something like the following. The 2 changes in the HTML you need to make are:
1) Add a class to your ul such as <ul data-self="2" class="nodes">. 2) Add a class to the wrapper ul such as <ul data-self="1" class="parent">.
var json = {};
$("#org1").find("ul.parent").each(function() {
var $this = $(this);
json[$this.data("self")] = {};
var $nodes = $this.find("ul.nodes");
$nodes.each(function() {
var children = $(this).find("li").map(function() {
return $(this).data("self")
}).get();
json[$this.data("self")][$(this).data("self")] = children;
});
});
alert (JSON.stringify(json));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="org1">
<li>
Main
<ul data-self="1" class="parent">
<li data-self="2" data-parent="1">A
<ul data-self="2" class="nodes">
<li data-self="5" data-parent="2">A1</li>
<li data-self="6" data-parent="2">A2</li>
<li data-self="7" data-parent="2">A3</li>
<li data-self="8" data-parent="2">A4</li>
<li data-self="9" data-parent="2">A5</li>
<li data-self="10" data-parent="2">A6</li>
</ul>
</li>
<li data-self="3" data-parent="1">B
<ul data-self="3" class="nodes">
<li data-self="11" data-parent="3">B1</li>
<li data-self="12" data-parent="3">B2</li>
<li data-self="13" data-parent="3">B3</li>
<li data-self="14" data-parent="3">B4</li>
</ul>
</li>
</ul>
</li>
</ul>

Categories

Resources