jQuery UI Sortable does not serialize/toArray child elements - javascript

I have the following list and when I call toArray or serialize it only offers me the parent <li>. I am trying to get hold of the whole hierarchy so I can store this information into a self referencing heirachy table in the database. The result here shows item_1,q_6,a_7,g_8. Where is item_3,item_4,item_5.
Thanks
<div id="example5">
<ul>
<li id="item_1">Item 1
<ul id="item_2">
<li id="item_3">Item 1 1<ul></ul></li>
<li id="item_4">Item 1 2<ul></ul></li>
<li id="item_5">Item 1 3<ul></ul></li>
</ul>
</li>
<li id="q_6">Item 2<ul></ul></li>
<li id="a_7">Item 3<ul></ul></li>
<li id="g_8">Item 4<ul></ul></li>
</ul>
</div>
<button id="fred">Click</button>
$("#fred").click(function () {
//var result = $('#example5 ul').sortable('toArray');
var result = $('#example5 ul').sortable('serialize'); //Neither work
alert(result);
});

As far as I can tell there's no default way of serializing nested sortable lists in jquery UI.
The best way to do it is to go through every child of "#example5 ul" and build your own structure (I would recommend JSON in this case) to be send to the server.

Related

How to query a data attribute value in javascript (no jquery)?

If I have a grid made up of ul's (the rows) and li's (the cells), I wanted to get a specific cell based on the data attribute values of the ul and the li:
document.querySelectorAll(div.grid ul[data-${this.y}] li[data-${this.x}]'_
When I searched on MDN, I only found how to retrieve the html element based on the data attribute, but not it's value.
Any pointers would be greatly appreciated - also no jQuery please.
You could use the String interpolation and get it worked.
Here is what you could do.
document.addEventListener('DOMContentLoaded', function() {
let ulData = 2,
liData = 4;
document.querySelector(`div.grid ul[data="${ulData}"] li[data="${liData}"]`).classList.add("red");
});
.red {
color: red;
}
<div class="grid">
<ul data="2">
<li data="1">
One
</li>
<li data="2">
Two
</li>
<li data="3">
Three
</li>
<li data="4">
Four
</li>
<li data="5">
Five
</li>
</ul>
</div>

AngularJS and Bootstrap: ng-repeat causing list to lose formatting

I'm attempting to have a ng-repeat that is retrieving content from an array and displaying it on a list. The content was originally JSON, but has been stringified before being pushed into the array.
The issue is that in bootstrap, this causes the list to lose it's formatting as so:
While, I would like it to look as so:
Here is my code for the dropdown component:
<li>
<a ng-controller="appCtrl" href="#">{{greeting.text}}, world</a>
</li>
<div ng-controller="PostsCtrl">
<li ng-repeat="eachResponse in response.text">
{{eachResponse}}
</li>
</div>
<li>
My dropdown
</li>
And my code for the function that returns an array from a JSON to the response.text in the 'PostsCtrl' controller used above:
function parseTheResponse(responsedataJSON) {
var obj = JSON.parse(JSON.stringify(responsedata));
var array = [];
for (var i = 0; i < obj.connectors.length; i++ ){
stringArray.push(JSON.stringify(obj.connectors[i].name));
}
return stringArray;
}
It's because of <div> inside <ul>. Try moving ng-controller to <ul> and removing that <div> wrapper.
Like the following:
<ul ng-controller="PostsCtrl">
<li>
<a ng-controller="appCtrl" href="#">{{greeting.text}}, world</a>
</li>
<li ng-repeat="eachResponse in response.text">
{{eachResponse}}
</li>
<li>
My dropdown
</li>
</ul>
PS. Looks like you are moving on with your hello world app (taking a look at your previous questions). Good work!

how to use set_id to rename node_id in jstree?

this is my rename function, none of the options i've tried work, i do know, that set_id is the function to use but how?
$('#jstree').on('rename_node.jstree', function (node,obj) {
var node_id = "calculated"// calculate node_id
// tried the following 3 options ..
....
$('#jstree').jstree(true).set_id(obj,node_id); //not working
obj.instance.set_id(this,node_id)// not working either
obj.instance.set_id(obj,node_id)//nope..
So how do i set the node_id in jstree?
I looked at the API http://www.jstree.com/api/#/?q=rename&f=rename_node.jstree, and I think you have to use obj.node.
$('#jstree').jstree(true).set_id(obj.node,node_id);
obj.text should contain the new name of the node, and obj.old the old name of the node.
EDIT: The link to the API documentation does not match the code example.
Here are the correct links:
To set the ID of a node: https://www.jstree.com/api/#/?f=set_id(obj,%20id)
To rename the node (set the text value): https://www.jstree.com/api/#/?f=rename_node(obj,%20val)
The first parameter you called node is actually the event object
Example creating a node then updating his autogenerated id
$('#jstree').on('create_node.jstree', function (e, obj) {
#...
$(this).jstree(true).set_id(obj.node, 42);
}
Try the following inside your on.() function:
$(this).attr("id", node_id);
Just set property id on the element you´re using to create the nodes.
<div id="jstree">
<ul>
#foreach($feelings as $feeling)
<li id="{{{$feeling->id}}}">{{{$feeling->name}}}
<ul>
#foreach($feeling->children as $feeling_children)
<li id="{{{$feeling_children->id}}}">{{{$feeling_children->name}}}
<ul>
#foreach($feeling_children->children as $feeling_children2)
<li id="{{{$feeling_children2->id}}}">{{{$feeling_children2->name}}}
<ul>
#foreach($feeling_children2->children as $feeling_children3)
<li id="{{{$feeling_children3->id}}}">{{{$feeling_children3->name}}}
<ul>
#foreach($feeling_children3->children as $feeling_children4)
<li id="{{{$feeling_children4->id}}}"> {{{$feeling_children4->name}}}</li>
#endforeach
</ul>
</li>
#endforeach
</ul>
</li>
#endforeach
</ul>
</li>
#endforeach
</ul>
</li>
#endforeach
</ul>

jQuery - Building a tree style list

My DOM is as follows
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
</ul>
</li>
</ul>
My jQuery in a in the bottom of the page is:
$("#Browse").click(function() {
$("#browse-one").html('<div class="ui-widget">Loading...</div>');
$("#browse-one").load('../api/browse.php?do=getFirst');
});
This script goes into the database and spits out raw LIs. After this runs the DOM is modified as follows
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
<li id="one-1" data-id="1">SOMETHING</li>
<li id="one-2" data-id="2">SOMETHING</li>
<li id="one-3" data-id="3">SOMETHING</li>
<li id="one-4" data-id="4">SOMETHING</li>
.
.
.
<li id="one-N" data-id="N">SOMETHING</li>
</ul>
</li>
</ul>
What is the proper jqueryish way to track clicks on these LIs. I want to extract the data-id of the clicked element and make a second API call to construct part two of the tree. For example if data-id="1"'s LI is clicked the DOM should be:
<ul>
<li id="Browse">
Browse
<ul id="browse-one">
<li id="one-1" data-id="1">SOMETHING
<ul id="Something Here">
<li id="two-1" data-id="1">HMM</li>
<li id="two-2" data-id="2">HMM</li>
<li id="two-3" data-id="3">HMM</li>
.
.
.
<li id="two-M" data-id="M">HMM</li>
</ul>
</li>
<li id="one-2" data-id="2">SOMETHING</li>
<li id="one-3" data-id="3">SOMETHING</li>
<li id="one-4" data-id="4">SOMETHING</li>
.
.
.
<li id="one-N" data-id="N">SOMETHING</li>
</ul>
</li>
</ul>
Im having trouble thinking of how i'de keep each of the inner UL's IDs unique. Sure I can do the "LEVEL-ID" as in "two-1" but I feel this is hackish and not the proper jquery way.
EDIT:
But now how do I track the children's clicks?? This doesn't seem valid but I hope you understand wht I'm trying to do
$("#Browse").click(function() {
$("#locations-browse").html('<div class="ui-widget">Loading...</div>');
$("#locations-browse").load('../api/browse.php?do=getFirst');
//Child is tracked
$("#locations-browse").delegate("li","click",function(evt){
var inner = $(this).append("<ul></ul>");
inner.html('<div class="ui-widget">Loading...</div>');
inner.load('../api/browse.php?do=getSecond');
$(this).delegate("li","click", function(evt) {
alert("Child ". $(this).data("id") . " is clicked";
});
});
});
EDIT 2:
Hmm this still is not working:
$("#Browse").click(function() {
$("#locations-browse").html('<div class="ui-widget">Loading...</div>');
$("#locations-browse").load('../api/browse.php?do=getFirst');
//Child is tracked
$("#locations-browse").delegate("li","click",function(evt){
$(this).append("<ul></ul>");
$(this).children("ul").load('../api/browse.php?do=getSecond?location-id='.$(this).data("id"));
$(this).delegate("li","click", function(evt) {
alert($(this).data("id"));
});
});
});
Delegate the event via li#Browse and reference the data-id attribute relative to the event's contextual element.
$('#Browse').on('click', 'li', function(evt) {
alert($(this).data('id'));
});
Incidentally, there's several out-of-the-box plugins that do what you need, just in case you didn't want to build you own, e.g. YUI Treeview or the one I wrote.

How to save HTML ul-li structure into javascript object

i have this following html structure usilg ul and li.
<ul class="treeview" id="productTree">
<li class="collapsable lastCollapsable">
<div class="hitarea collapsable-hitarea lastCollapsable-hitarea"></div>
<span id="top1" class="">top1</span>
<ul>
<li class="collapsable lastCollapsable">
<span class="">mod1</span>
<ul>
<li class="last">
<span>bottom1</span>
</li>
</ul>
</li>
</ul>
</li>
<li class="collapsable lastCollapsable">
<span id="top2" class="">top2</span>
<ul>
<li class="collapsable lastCollapsable">
<span class="">mid2</span>
<ul>
<li class="last">
<span>bottom2</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
the website allows user to add more data under this structure and am using jquery treeview to show the tree structure dynamically.
Now i need to save this whole ul-li structure into a js object for future use in the website. how do i achieve this? the last node("bottom1 and bottom2 here") has a class "last" if that helps.
as we can add data dynamically we can be sure how much levels of ul li is there at the end when user clicks "save"
You can use recursive function to save a tree object;
function save(obj_ul, tree){
var obj_lis = obj_ul.find("li")
if (obj_lis.length == 0) return;
obj_lis.each(function(){
var $this = $(this);
if($this.parent("ul").get(0) == obj_ul.get(0))
{
tree.push({
name : $this.find('> span').text(),
child : save($this.find("ul").first(), [])
});
}
});
return tree;
}
console.log(save($('#productTree'), []));
If you want to reprouce the same thing verbatim, as a string of HTML elsewhere on the site, you could just do this? Then .append() or .prepend() treeview where you like.
​var treeview = $('#productTree').parent().html()
Assuming you want JSON:
function save(){
var tmp = [];
$('#productTree li.collapsable').each(function(){
var $this = $(this),
$spans = $this.find('span'),
o = [];
$spans.each(function(){
o.push($(this).text())
})
tmp.push(o);
});
return tmp;
}
You could also use map() to accomplish the same thing, too.
EDIT: Updated, assuming your text will live inside a span. This will create an array of arrays, each containing the text from the spans inside each of your list-items.

Categories