How to get selected li value - javascript

I have an array list as shown below
var items = ['Iphones', 'Samsung', 'Huawei'] which I append to a li as below.
HTML & JS
<div id="host">
<div class="data_box"></div>
</div>
$.ajax({
dataType: 'json',
success: function (results) {
$('.data_box').html('<li class="li_of_phones">'+results.toString().split(',').join('<br/>')+'</li>').slideDown();
},});
<script>
$('#host').on('click', '.li_of_phones', function () {
console.log($(this).text());
});
</script>
When I try to get the selected li when user clicks, it returns the array i.e Iphones,Samsung,Huawei instead of the selected phone (may be iphones)
Why am I not getting the selected phone when user clicks on the li but then it returns the all phones in the array to user?

It seems you receive the results from the ajax call as a comma separated string and then set it in a single <li> element with the li_of_phones class.
You could loop the splitted response in a foreach and create different li elements for each result.
const results = 'Iphones, Samsung, Huawei';
let phonesList = '';
results.split(',').forEach(phone => {
phonesList += '<li class="li_of_phones">' + phone.trim() + '</li>';
});
$('.data_box').html(phonesList).slideDown();
$('#host').on('click', '.li_of_phones', function () {
console.log($(this).text());
});
.as-console-wrapper { max-height: 5.5em !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="host">
<ul class="data_box"></ul>
</div>
You might have to change some css styles of the resulting list items.

You should add an event on li. I have created a small example.
$('li').click(function(e) {
console.log(e.target.innerHTML);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>

Related

How to appropriately apply styles to a functioning get request using JQuery?

So here's whats going on, I have a couple scenarios where I can't seem to apply any styles to content coming from a get request, and on one of them I managed to be able to but it wouldn't be considered best practice.
Premise:
I have an empty Ul to which Li's will be attached from a GET request to an API.
Scenarios
1) I create DOM objects using JQuery and append LI <-- SPAN <-- string to the empty UL and then state that all the children of the UL will be colored green.
(this does not work & yes I could target the UL and have everything inherit the styles but that wont work for what I have in mind)
2) I append a string which contains HTML markup within it to then add styles and concat them with what the GET request spits out. ( for some reason it seems to work this way but I really don't want to be creating LI's and SPANS + classes all in one string)
//scenario 1
var $orders = $("#orders");
$.ajax({
type: 'GET',
url: 'http://rest.learncode.academy/api/johnbob/friends',
success: function (data) {
$.each(data, function (i, item) {
if (item.name && item.drink) {
var $spn = $("<span></span>");
var $lli = $("<li></li>");
// $spn.append(String(item.name));
$spn.css({width: "20px"});
$orders.append($lli).append($spn).append("name: "+item.name+", Order: " + item.drink);
$orders.children().css({ color: "green" });
console.log($spn);
}
})
}
});
/* scenario 2
var $orders = $("#orders");
$.ajax({
type: 'GET',
url: 'http://rest.learncode.academy/api/johnbob/friends',
success: function (data) {
$.each(data, function (i, item) {
if (item.name && item.drink) {
var $spn = $("<span>hell</span>");
var $lli = $("<li></li>")
// $spn.append(String(item.name));
$spn.css({width: "20px"});
$orders.append("<li>Name: <span class='tato'>" + item.name + ",</span> Order: " + item.drink + "</li>");
$orders.children().css({ color: "green" });
console.log($spn);
}
})
}
});
*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Coffee Orders</h2>
<br />
<ul id="orders">
<li>control group</li>
</ul>
<br />
<h4>Add a coffee order</h4>
<p>name: <input type="text" id="name"></p>
<p>drink: <input type="text" id="drink"></p>
<button id="add_order">Add!</button>
I haven't been able to find a reliable answer as to why this is happening, eventually I'll want to line up the orders regardless of the name length using a span.
edit:
What was happening (as stated in the answer) was I was appending empty LI's SPANs and Strings to the original UL. When using append() keep in mind anything you add (in a chain form) will be appended to the original stated element and not the previous one.
Side note:
For more information on better practice of templating incoming GET stuff check out this vid I found.
https://www.youtube.com/watch?v=GbNWPn8vodo&index=9&list=PLoYCgNOIyGABdI2V8I_SWo22tFpgh2s6_
As noted by #Taplar the issue is use of .append(). You are appending <span> elements and #text nodes to <ul> at
$orders.append($lli).append($spn).append("name: "+item.name+", Order: " + item.drink);
which are not valid child elements of <ul>
Permitted content zero or more <li> elements, which in turn often
contain nested <ol> or <ul> elements.
To correct issue, set #text node as .innerHTML of <span> element, and span element as .innerHTML of <li> element using html of jQuery(html, attributes) function attributes property.
Also set span css display property to block for width property to be applied to the element.
//scenario 1
var $orders = $("#orders");
$.ajax({
type: 'GET',
url: 'http://rest.learncode.academy/api/johnbob/friends',
success: function(data) {
$.each(data, function(i, item) {
if (item.name && item.drink) {
var $spn = $("<span></span>", {
html: "name: "
+ item.name
+ ", Order: "
+ item.drink,
css: {
width: "20px",
display: "block",
position: "relative"
}
});
var $lli = $("<li></li>", {
html: $spn
});
$orders.append($lli)
.children().css("color", "green");
}
})
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Coffee Orders</h2>
<br />
<ul id="orders">
<li>control group</li>
</ul>
<br />
<h4>Add a coffee order</h4>
<p>name:
<input type="text" id="name">
</p>
<p>drink:
<input type="text" id="drink">
</p>
<button id="add_order">Add!</button>

radomize ul tag not working

this is probably an easy question for you guys but I'm very new to coding and can't figure out this. I have a code that I want to randomize the given choices in the questions, and I've found a script online that does that but it's not working. I don't know what the
// shuffle only elements that don't have "group" class
$ul.find("li[class!='single_question', 'question', 'title', 'text']").each(function() {
means so I tried to put all id that I don't need to randomize in it but it's still not working.
Can someone help me this please? Also is there anyway I can add choice "A", choice "B", choice "C", and choice "D" in front of each given options so even after the options(answers) are randomized, the A,B,C,D options will still be in order? Thank you. Here's the code:
HTML:
<!DOCTYPE html>
<html>
<body>
<script src="JQ.js"></script>
<script src="function.js"></script>
<link href="style.css" rel="stylesheet" />
<div id="quiz_container">
<ul class="quiz_container">
<li class="single_question" data-question-id="1" data-correct-answer="1">
<div class="question">
<h1 class="title">P.1 Grammar Review</h1>
<p class="text">1. "What is your name__"</p>
</div>
<ul class="options">
<li value="1">?</li>
<li value="2">.</li>
<li value="3">,</li>
</ul>
<div class="result"></div>
</li>
<li class="single_question" data-question-id="2" data-correct-answer="b">
<div class="question">
<p class="text">2. "Do you like the banana__"</p>
</div>
<ul class="options">
<li value="a">.</li>
<li value="b">?</li>
<li value="c">,</li>
</ul>
<div class="result"></div>
</li>
</div>
</body>
</html>
JS:
$(document).ready(function () {
/*
* shuffles the array
* #param {Array} myArray array to shuffle
*/
function shuffleArray(myArray) {
for (var i = myArray.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = myArray[i];
myArray[i] = myArray[j];
myArray[j] = temp;
}
return myArray;
}
var $ul, $li, li_content, li_list;
// find all lists to shuffle
$("#quiz_container > ul").each(function () {
$ul = $(this);
li_list = [];
// shuffle only elements that don't have "group" class
$ul.find("li[class!='single_question', 'question', 'title', 'text']").each(function () {
// add content to the array and remove item from the DOM
li_list.push($(this).html());
$(this).remove();
});
// shuffle the list
li_list = shuffleArray(li_list);
while (li_content = li_list.pop()) {
// create <li> element and put it back to the DOM
$li = $("<li />").html(li_content);
$ul.append($li);
}
});
$("#contact_div").show();
});
$(document).on('click', '.single_question .options li', function () {
// Save the question of the clicked option
question = $(this).parents('.single_question');
// Remove If Anyother option is already selected
question.find('.selected').removeClass('selected');
// Add selected class to the clicked li
$(this).addClass('selected');
// selected option value
selected_answer_value = $(this).attr("value");
// Value of correct answer from '.single-question' attribute
correct_answer_value = question.attr("data-correct-answer");
correct_answer_text = question.find('.options').find("li[value='" + correct_answer_value + "']").text();
if (correct_answer_value == selected_answer_value)
result = "<div class='correct'> Correct ! </div>";
else
result = "<div class='wrong'> Correct answer is -> " + correct_answer_text + "</div>";
// Write the result of the question
$(this).parents('.single_question').find('.result').html(result);
// Calculate the score
score_calculator();
});
/**
* It loops through every question and increments the value when "data-correct-answer" value and "option's value" are same
*/
function score_calculator() {
score = 0;
$('.single_question').each(function () {
question = $(this);
if (question.attr('data-correct-answer') == question.find('.selected').attr("value")) {
score++;
}
});
$('.correct_answers').html(score);
}
It looks like you're using jQuery, even though the question isn't tagged as such. If that's the case, you can use a code snippet written by Chris Coyier of CSS-Tricks called shuffle children.
Here's an example of the code in action.
$.fn.shuffleChildren = function() {
$.each(this.get(), function(index, el) {
var $el = $(el);
var $find = $el.children();
$find.sort(function() {
return 0.5 - Math.random();
});
$el.empty();
$find.appendTo($el);
});
};
$("ul.randomized").shuffleChildren();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Static List:</h4>
<ul>
<li>First element</li>
<li>Second element</li>
<li>Third element</li>
<li>Fourth element</li>
</ul>
<h4>Randomized List:</h4>
<ul class="randomized">
<li>First element</li>
<li>Second element</li>
<li>Third element</li>
<li>Fourth element</li>
</ul>
In order to apply it to your own code, all you'd need to do is modify the CSS selector at the bottom of the jQuery snippet. In your case, ul.options might be a good choice.
Here are a couple of examples using your markup:
jsFiddle
Self-Contained HTML Doc

create simple js object and store them into js array

Inside html dom I have following structure
<div id="myTitles">
<ul>
<li>
Title:<title>A</title><br>
Second title: <secTitle>B</secTitle><br>
Third title: <thirdTitle>3</thirdTitle>
</li>
<hr>
<li>
Title:<title>B</title><br>
Second title: <secTitle>C</secTitle><br>
Third title: <thirdTitle>9</thirdTitle>
</li>
</ul>
</div>
Number of list elements inside ul of myTitles div is unknown on runtime. So I'm taking var nrOfTitles = $('#myTitles ul li').length; to determine how many is there.
Now, I want to create some simple javascript object which will hold those values (stored inside this semantic tags (title, secTitle, thirdTitle)) and store them inside js array.
var items = $("#myTitles > ul > li");
var arr = [];
items.each(function(){
arr.push([$(this).find("title").text(),$(this).find("secTitle").text(),$(this).find("thirdTitle").text()])
})
With your current combination of <li>s it would contain:
[["A","B","3"],["B","C","9"]]
Or you can store the properties as objects:
var items = $("#myTitles > ul > li");
var arr = [];
items.each(function(){
arr.push({title:$(this).find("title").text(),secTitle:$(this).find("secTitle").text(),thirdTitle:$(this).find("thirdTitle").text()})
})
Then you would get
[{title:"A",secTitle:"B",thirdTitle:"3"},{title:"B",secTitle:"C",thirdTitle:"9"}]
You can use $.fn.map method to conveniently create an array of objects:
var obj = $('#myTitles ul li').map(function() {
return {
title: $(this).find('title').text(),
secTitle: $(this).find('secTitle').text(),
thirdTitle: $(this).find('thirdTitle').text()
};
}).get();
alert(JSON.stringify(obj, null, 4));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myTitles">
<ul>
<li>
Title:<title>A</title><br>
Second title: <secTitle>B</secTitle><br>
Third title: <thirdTitle>3</thirdTitle>
</li>
<hr>
<li>
Title:<title>B</title><br>
Second title: <secTitle>C</secTitle><br>
Third title: <thirdTitle>9</thirdTitle>
</li>
</ul>
</div>
But since you are using custom tags in HTML, remember to create them for IE8, if you plan so support this browser, like document.createElement('title');.

Load data, insert after and slidetoggle

I`m kind of novice in jquery and want to make a sliding table.
The orinal table has 3 levels:
<ul class="categories">
<li id="category1">1 element</li> //parentid=0
<li id="category2">2 element</li> //parentid=0
<ul>
<li id="category3">1 element of element id2</li> //parentid=2
<ul>
<li id="category4">1 element id3</li> //parentid=3
</ul>
</li>
</ul>
</li>
</ul>
The first level elements have parentid = 0, id=1++, the next level have nested parentid and there own id and so on.
Page loads with only 1 level with parentid = 0.
<ul class="categories">
<li id="category1">1 element</li> //parentid=0
<li id="category2">2 element</li> //parentid=0
</ul>
Then I want to click the li, take id ID - go to file, execute mysql, get the new table in variable, bring it back and slideToggle it under LI.
php side
if(isset($_POST['subcategory'])){
$subcategory = str_replace('category', '', $_POST['subcategory']);
echo build_category_tree($subcategory); // builds the UL tree
}
this returns me id, i need to return the list and toggle it.
NOW the new UL is connected BUT i jquery cant work with it, updated the script with the one below but still cant.
UPDATED JQuery
$(".tablecategoryname").on('click', function(){
var $a = $(this).closest('li').attr('id');
var $c = $(this).closest('li');
$.ajax({
type: "POST",
url: "functions.php",
data: {subcategory:$a},
cache: false,
success: function(data)
{
$(data).hide().insertAfter($c).slideDown(400);
}
});
});
ID's should not contain just a number (or start with a number), you should probably use #a1 or something similar. In the data parameter you're sending an object, and equalsigns does'nt really work.
$(".table li").on('click', function(){
var self = this;
$.ajax({
type: "POST",
url: "functions.php",
data: {id : self.id},
cache: false
}).done(function(data) {
//guessing you're returning valid HTML
$(data).hide().insertAfter(self).slideDown(400);
});
});
EDIT:
Your build_category_tree() function needs to return the HTML so you can echo it back to the ajax request:
if(isset($_POST['subcategory'])){
echo $subcategory = str_replace('category', '', $_POST['subcategory']);
$ULtree = build_category_tree($subcategory); // builds the UL tree
echo $ULtree; //echo back to Ajax
}
You should put an id in your main ul to catch his parent and them toggle the list inside the main ul.
$("ul.umenu > li).click(function (e) {
e.preventDefault();
var element = $(this);
if (element.parent().find("ul").is(":visible")) {
} else {
$("ul.umain> li > ul").slideUp();
element.parent().find("ul").slideToggle("fast");
}
});

Lists alphabetical ordered by javascript with letter headings

I have a list like this:
<ul id="list">
<li>Adam</li>
<li>Alex</li>
...
<li>Zara</li>
</ul>
And it is already alphabetical ordered by this JavaScript:
var mylist = $('#list');
var listitems = mylist.children('li').get();
listitems.sort(function(a, b) {
return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase());
})
$.each(listitems, function(idx, itm) { mylist.append(itm); });
Now I need to set the list like this:
<ul id="list">
<li id="a"><a name="a" class="title">A</a>
<ul>
<li>Adam</li>
<li>Alex</li>
</ul>
</li>
<li id="b"><a name="b" class="title">B</a>
<ul>
<li>Barry</li>
<li>Becky</li>
</ul>
</li>
...
...
...
<li id="z"><a name="z" class="title">z</a>
<ul>
<li>zavv</li>
<li>zora</li>
</ul>
</li>
</ul>
To use the list in this Apple Style Slider.
Do you know how can I do it with JavaScript?
It would be easiest (I guess) to collect all li elements in an object first (categorized bei their content's initial letter) and then sort those lists separately. Since code says more than a thousand words, here's how I would do that:
var list = { letters: [] }; //object to collect the li elements and a list of initial letters
$("#list").children("li").each(function(){
var itmLetter = $(this).text().substring(0,1).toUpperCase();
if (!(itmLetter in list)) {
list[itmLetter] = [];
list.letters.push(itmLetter);
}
list[itmLetter].push($(this)); //add li element to the letter's array in the list object
});
list.letters.sort(); //sort all available letters to iterate over them
$.each(list.letters, function(i, letter){
list[letter].sort(function(a, b) {
return $(a).text().toUpperCase().localeCompare($(b).text().toUpperCase()); //sort li elements of one letter
});
var ul = $("<ul/>"); //create new dom element and add li elements
$.each(list[letter], function(idx, itm){
ul.append(itm);
});
$("#list").append($("<li/>").append($("<a/>").attr("name", letter.toLowerCase()).addClass("title").html(letter)).append(ul)); //add the list to a new li and to #list ul
});
JSFiddle: http://jsfiddle.net/KnC6M/
Thanks #Aletheios, I updated your solution to make it more efficient solution with the use of css without removing list by $("#list").empty();
Assuming your list is already sorted.
var letters = [];
$("#list").children("li").each(function(i){
var itmLetter = $(this).text().trim().substring(0,1).toUpperCase();
if (letters.indexOf(itmLetter)<0) {
console.log(`${itmLetter} is not in ${letters} and index is ${i}`);
$(`#list li:nth-child(${i+1})`).addClass("AddContent").attr('data-content',itmLetter);
letters.push(itmLetter);
} else {
console.log(`${itmLetter} is in ${letters}`);
}
});
CSS:
#list{
margin-left: 15px;
}
li.AddContent:before {
content: attr(data-content);
margin-left: -15px;
display: block;
}
HTML:
<ul id="list">
<li> Zara</li>
<li> Adam</li>
<li> Alex</li>
<li> Toby</li>
</ul>
JSfiddle: http://jsfiddle.net/KnC6M/105/
I was searching for something similar, I wanted to sort an array in alphabetically grouped manner. Here is my code which is little modified version of #Aletheios code. Hope it helps.
var list = { letters: [] };
var words = {let: ['abc', 'aabbgg', 'cda', 'hello', 'bca']};
$.each(words.let, function(){
var itLetter = this.substring(0,1).toUpperCase();
if(!(itLetter in list)){
list[itLetter] = [];
list.letters.push(itLetter);
}
list[itLetter].push($(this));
});
list.letters.sort();
$.each(list.letters, function(i, letter){
var ul = $("<ul/>");
var li = $('<li/>');
$.each(list[letter], function(idx, itm){
ul.append('<li>'+ itm[0] +'</li>');
console.log(itm);
});
$("body").append($("<li/>").append($("<a/>").attr("name", letter.toLowerCase()).addClass("title").html(letter)).append(ul));
});
Here is the fiddle.
http://jsfiddle.net/checkomkar/x8taqcnk/

Categories