Access names of checked nodes without all the sub nodes' names - javascript

I'm using jstree and I want to access the IDs and names of all checked nodes in my HTML tree in order to present them together in a summary.
This is my code:
$("#summary").click(function () {
var id_arr = new Array();
var text_arr = new Array();
$("#tree").jstree('get_checked').each(function (index) {
id_arr.push($(this).attr("id"));
text_arr.push($(this).text());
});
alert("Your Selection: " + id_arr.join() + " " + text_arr.join());
});
While id_arr.push($(this).attr("id")); returns only the IDs of the relevant checked nodes (only the parent node ID when all children of the parent node are checked as well), text_arr.push($(this).text()); returns all the names of the checked nodes (name of checked parent and names of all of its children).
Do you have any ideas how to return only the names of the checked parent?
I already considered adding a hidden HTML attribute (as in <li id="123"> <a title="ID:123" hidden="name of node 123">name of node 123</a></li>) to my tree nodes and using .attr("hidden") instead of accessing node.text() but I think that there must be a better solution.
Any help would be much appreciated!
Update:
The HTML of the tree (my real tree is quite extensive but I think this one will do):
<div id="tree">
<li id="123"> <a title="ID:123">tree</a>
<ul>
<li id="234"> <a title="ID:234">leaf tree</a>
<ul>
<li id="345"> <a title="ID:345">oak</a>
<ul>
<li id="456"> <a title="ID:456">white oak</a></li>
<li id="567"> <a title="ID:567">German oak</a></li>
</ul>
</li>
<li id="678"> <a title="ID:678">lime</a></li>
</ul>
</li>
<li id="789"> <a title="ID:789">conifer</a>
<ul>
<li id="890"> <a title="ID:890">pine</a></li>
<li id="901"> <a title="ID:901">spruce</a></li>
</ul>
</li>
</ul>
</li>
</div>
Example: When choosing "oak", the return should be only "345 oak" and not "345 oak white oak German oak".
By the way, my idea with "hidden" doesn't work, because the elements written in there are, well, hidden.

I found a solution:
text_arr.push($(this).find("a:first").text());
The result of .text() is a string containing the combined text of all matched elements; in this case all text contained between the li-tags of the element referenced by $(this), including the text of the sub nodes.
By adding .find("a:first").text() only the text between the first a-tag is contained in the string.

Related

How to target a specific element from a group of them having the same class/id in javascript?

I want to copy the text in the <li> tag using JavaScript. It should be copied when the <li> tag is clicked. All <li> tags have the same class as they will get the same formatting through CSS.
As per my research, we need to specify the button a target class which it will copy to clipboard(Using clipboard.js). The <li> tag will be generated through js so, to give different id to each one of them will be difficult and will increase the code and reduce the speed too.
So how can copy the text of the li tag that is being clicked through js/jquery/clipboard.js etc.
<ul>
<li class="data">Lorem ipdolor.</li>
<li class="data">Lo ripsum dolor.</li>
<li class="data">Lorepsum dor.</li>
</ul>
There are different methods but two that stand up on top.
$(function() {
$("li[class='data']").click(function(e) {
// 1) Use this reference
console.log("1: " + $(this).text());
// 2) Use Event Target
console.log("2: " + $(e.target).text());
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="data">Lorem ipdolor.</li>
<li class="data">Lo ripsum dolor.</li>
<li class="data">Lorepsum dor.</li>
</ul>
You can put an id on ul:
<ul id="dataContainer">
<li class="data">sometext</li>
<li class="data">sometext1</li>
<li class="data">sometext2</li>
<li class="data">sometext3</li>
</ul>
Then:
document.getElementById('dataContainer').addEventListener('click', function(e){
console.log(e.target.innerText);
});

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>

To add class="current" Dynamically

I have Menu list which contains Sub-Menu as shown in the code below.
<li class="current">
<span class="icon4"></span>Subscriptions
<ul class="sub-menu">
<li>View Subscriptions
</li>
<li class="#((ViewBag.PageName == " Subscription ") ? "active " : " ")">Manage Subscription Plans
</li>
</ul>
</li>
<li class="current">
<span class="icon5"></span>Administration
<ul class="sub-menu">
<li class="#((ViewBag.PageName == " AssetPage ") ? "active " : " ")">Assets
</li>
<li>Configure Text
</li>
<li>Error Log
</li>
<li>Product Settings
</li>
</ul>
</li>
<li class="current">
<span class="icon6"></span>Promo Codes
<ul class="sub-menu">
<li>Manage Promo Code
</li>
<li>Used Promo Code
</li>
</ul>
</li>
Here Subscription,Administration,Promo Codes are Menu Lists which contains Sub-Menu Lists under them.
The thing is I want to apply class=current dynamically when a user clicks on Subscription,Administration,Promo Codes`.
And I am doing this in LayoutPage of MVC.
Any help will be appreciated.
Here you have a working solution: https://jsfiddle.net/c4h3sup9/
You have to use a little bit of Javascript for that.
You have to give the listitems a other class name like in my example "operator"
document.body.addEventListener("click", function(e){
if(e.target && e.target.className == "operator"){
var actives = document.getElementsByClassName("active");
actives[0].setAttribute("class", "operator");
e.target.setAttribute("class", "active");
}
});
for this example you need to assing one element as active from the beginning.
Note:
LI elements are never parents of UL.
The order is:
Unordered List (Plural) -> List item (Singular, Child).
You might want to correct that as it is not standard conform.
To add the class name to the parent <li> element, give the main links a class name. Assuming you also want to remove it from any <li> elements that already have it, also give them a class name
<li class="container">
<span class="icon4"></span>Subscriptions
and the script will be
$('.mainmenu').click(function() {
$('.container').removeClass('current'); // remove any previous
$(this).closest('.container').addClass('current');
});
In addition, if when you navigate to one of the views with this layout, and what to add the class name to the appropriate element, then you can give the <li> elements an id attribute
<li id="subscriptions" class="container">
....
</li>
<li id="administration" class="container">
....
and in the GET method, pass the value of the id to the view (e.g. using ViewBag
public ActionResult ConfigureText()
{
ViewBag.Menu = "administration";
....
return View(...);
}
and add a script that runs when the page first loads
var menu = '#ViewBag.Menu";
$('#' + menu).addClass('current');

How to get li value and print it again

I am creating a website for a university project.
What i have is 3 tables that contain 1 list of links each. The links represent lessons and to what they link it doesn't matter. When a student chooses a lesson then that lesson is supposed to be presented at the bottom of the page without leaving the list.
My code is the following:
<!DOCTYPE HTML>
<html>
<link rel="stylesheet" type="text/css" href="style.css"> <!--Links the page with my style.css file-->
<body>
<head>
<title>Competences</title>
</head>
<?php
$name = $_GET['name'];
$surname = $_GET['surname'];
echo "<h3>Hello " .$name." ".$surname"</h3>" ;
?>
<div class="background">
<h5>Below are various competences organised into three main categories. Select the ones you think are more important for your studies by clicking on them.</h5>
<div class="box" style="inline" id="1">
<h2>INSTRUMENTAL</h2>
<ul>
<h4>
<li onClick="Copy()">Capacity for analysis and synthesis</li>
<li onClick="Copy()">Capacity for organisation and planning</li>
<li onClick="Copy()">Basic general knowledge</li>
<li onClick="Copy()">Grounding in basic knowledge of the profession</li>
<li onClick="Copy()">Oral and written communication in your native language</li>
<li onClick="Copy()">Knowledge of a second language</li>
<li onClick="Copy()">Elementary computing skills</li>
<li onClick="Copy()">Information management skills (ability to retrieve and analyse information from different sources)</li>
<li onClick="Copy()">Problem Solving</li>
<li onClick="Copy()">Decision-making</li>
</h4>
</ul>
</div>
<div class="box2" style="inline" id="2">
<h2>INTERPERSONAL</h2>
<ul>
<h4>
<li onClick="Copy()">Critical and self-critical abilities</li>
<li onClick="Copy()">Teamwork</li>
<li onClick="Copy()">Interpersonal skills</li>
<li onClick="Copy()">Ability to work in an interdisciplinary team</li>
<li onClick="Copy()">Ability to communicate with experts in other fields</li>
<li onClick="Copy()">Appreciation of diversity and multiculturality</li>
<li onClick="Copy()">Ability to work in an international context</li>
<li onClick="Copy()">Ethical commitment</li>
</h4>
</ul>
</div>
<div class="box3" style="inline" id="3">
<h2>SYSTEMIC</h2>
<ul>
<h4>
<li onClick="Copy()">Capacity of applying knowledge in practice</li>
<li onclick="Copy()">Research Skills</li>
<li onClick="Copy()">Capacity to learn</li>
<li onClick="Copy()">Capacity to adapt to new situations</li>
<li onClick="Copy()">Capacity for generating new ideas(creativity)</li>
<li onClick="Copy()">Leadership</li>
<li onClick="Copy()">Understanding of cultures and customs of other countries</li>
<li onClick="Copy()">Ability to work autonomously</li>
<li onClick="Copy()">Project design and management</li>
<li onClick="Copy()">Initiative and entrepreneurial spirit</li>
<li onClick="Copy()">Concern for quality</li>
<li onClick="Copy()">Will to succeed</li>
</h4>
</ul>
</div>
</div>
<form action="step3.php" method="get">
<input type="submit" value="Submit Choices"/>
</form>
<h5>You have selected the following competences:</h5>
<script type="text/javascript">
var count = new Array();
var i=0;
var column_id = "id";
var col1=0;
var col2=0;
var col3=0;
function Copy()
{
count[i] = "value";
i++;
var div = document.createElement('div');
div.innerHTML = '<div>' + count[i] + '</div>';
if (column_id==1)
{
col1+=1;
}
else if (column_id==2)
{
col2+=1;
}
else if (column_id==3)
{
col3+=1;
}
div.innerHTML = '<div>'Competences Selected: + col1 + " Instrumental" + col2 + " Interpersonal" + col3 +" Systemic."'</div>';
}
</script>
</body>
</html>
Also in competences Selected I will have to tell to the student the number of subjects he has selected from Instrumental list, Interpersonal list and Systemic List.
lets say for example my list is that :
Instrumental
1.option1
2.option2
if option 1 is selected as the lesson from instumental then i will have something like:
Competences Selected: 1 Instumental,0 Interpersonal, 0 Systemic
1.option1
As you can see i tried doing it with javascript but i am not quite sure how to make it work.. I don't know if value is what i should take into consideration or if i am supposed to do it with javascript.
I am not 100% sure what you are doing here, but there are a few things you may want to look at: -
In the line count(i) = "value"; I assume that you are refering to the array. In which case it should be count[i] = "value"
In the line "<div>count(i)</div>"; I assume that you mean to have the value at the count array index in the div, in which case you want div.innerHTML = '<div>' + count[i] + '</div>';
You have onClick="count()" referencing a count() method but also a global count() array. Change the name of the function to avoid confusion.
You have a javascript function called onclick, to avoid confusion give it a name that describes what the function does rather than using the generic onclick name.
Try to reduce the problem you are having to the smallest subset of self-contained code and you will be more likely to get answers.
Update:
Based on your updated code, I think I can see what you are wanting to do. See here for a cut down example, you should be able to apply the same to the rest of the page.
Some notes: -
calling count[i] = "value" will not get you the value of the <li> element. You need to pass the element and call innerHTML or retrieve it in the html.
You actually want the value of the as far as I can tell, so you might as well put the onclick in the <a>.
calling var column_id = "id"; will not get you the id of the containing div. You need to first get the div by a selector. I suggest you look into using jQuery to achieve this. For brevity, I just passed the value in the javascript call.
I left an alert in the Copy() function so you can see what is passed in, you will want to remove this.

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.

Categories