JQuery Append removing characters in IE and Edge - javascript

Using JQuery, when I loop through an array and append the values to a UL it works fine in Chrome and Firefox. In IE and Edge it truncates the value if it starts with a number followed by a dash or underscore.
var listItems = $('#list1');
var result = ['1-2-3', '1_2_3', 'a-b-c', 'a_b_c'];
$.each(result, function(key, value) {
listItems.append($('<li/>', {
value: value,
text: value
}))
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="list1"></ul>
Expected Result:
<ul>
<li value="1-2-3">1-2-3</li>
<li value="1_2_3">1_2_3</li>
<li value="a-b-c">a-b-c</li>
<li value="a_b_c">a_b_c</li>
</ul>
Actual Result:
<ul>
<li value="1">1-2-3</li>
<li value="1">1_2_3</li>
<li value="a-b-c">a-b-c</li>
<li value="a_b_c">a_b_c</li>
</ul>

Don't use value. According to the specification, the value of an li element must be an integer:
The value attribute, if present, must be a valid integer. It is used to determine the ordinal value of the list item, when the li's list owner is an ol element.
IE and Edge are enforcing this requirement by extracting the integer prefix from the values; they only leave the value alone if it doesn't begin with an integer.
If you need to attach custom data to an element, use data-XXX attributes, which can be set in jQuery with the data: property when creating the element, and you can fetch and update with the .data() method.
var listItems = $('#list1');
var result = ['1-2-3', '1_2_3', 'a-b-c', 'a_b_c'];
$.each(result, function(key, value) {
listItems.append($('<li/>', {
data: {
value: value
},
text: value
}))
});
$("li").click(function() {
alert($(this).data("value"));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="list1"></ul>

As an FYI, I wound up adding a data-value attribute to the LI instead of using jQuery.data()
$.each(result, function (key, value) {
listItems.append($('<li/>', {
text: value
}).attr("data-value", value))
}
);
Thsnks again for your help!

Related

jstree disable_node not working when id is string

I want to disable some nodes in jstree plugin. I used the following code for this purpose and everything was fine.
var tidlist = ['17f6171a-4da6-4904-ae75-c290eb101717', '3fbb9e60-13f2-48e9-9323-003cb46dbb5d'];
for (var i = 0; i < tidlist.length; i++)
{
$.jstree.reference('#jstree1').disable_node(tidlist[i]);
}
In this example, the IDs are defined as fixed. But the IDs are not fixed and come from the controller.
Controller
ViewBag.rlist = JsonConvert.SerializeObject(tQuery.Select(t => t.CenterUserID).ToList());
View
var tidlist = [];
tidlist = '#ViewBag.rlist';
for (var i = 0; i < tidlist.length; i++)
{
$.jstree.reference('#jstree1').disable_node(tidlist[i]);
}
But this code does not work.
Try to set the break point the debug the JavaScript via F12 developer tools, then, you can see the tidlist value should be System.Collections.Generic.List1[System.String];`, instead of the string array.
The issue is that we can't directly access the ViewBag value in the JavaScript.
To transfer the string array from controller to JavaScript script, first, in the controller, convert the array or list to a string (with separator), then, in the View page, use a hidden field to store the ViewBag value, finally, in the JavaScript script, get value from the hidden field and call the Split () method to convert the string value to an array.
Code as below:
Controller:
var strlist = new List<string>() { "17f6171a-4da6-4904-ae75-c290eb101717", "3fbb9e60-13f2-48e9-9323-003cb46dbb5d" };
ViewBag.rlist = string.Join(',', strlist);
View Page:
<div id="jstree">
<!-- in this example the tree is populated from inline HTML -->
<ul>
<li>
Root node 1
<ul>
<li id="17f6171a-4da6-4904-ae75-c290eb101717">Child node 1</li>
<li>Child node 2</li>
<li id="3fbb9e60-13f2-48e9-9323-003cb46dbb5d">Child node 3</li>
<li>Child node 4</li>
</ul>
</li>
<li>Root node 2</li>
</ul>
</div>
<button>demo button</button>
<input type="hidden" id="myInput" data-myValue="#ViewBag.rlist" />
#section Scripts{
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
<script>
$(function () {
// 6 create an instance when the DOM is ready
$('#jstree').jstree();
// 7 bind to events triggered on the tree
$('#jstree').on("changed.jstree", function (e, data) {
console.log(data.selected);
});
// 8 interact with the tree - either way is OK
$('button').on('click', function () {
// var tidlist = ['17f6171a-4da6-4904-ae75-c290eb101717', '3fbb9e60-13f2-48e9-9323-003cb46dbb5d'];
var tidlist = $("#myInput").attr("data-myValue").split(","); //the result is an string array, like: ['17f6171a-4da6-4904-ae75-c290eb101717', '3fbb9e60-13f2-48e9-9323-003cb46dbb5d']
for (var i = 0; i < tidlist.length; i++) {
$.jstree.reference('#jstree').select_node(tidlist[i]);
}
});
});
</script>
}
The result as below:

Get index of an element from a NodeList

I have a simple list:
<ul id="list">
<li id="item-1">1</li>
<li id="item-2" style="display: none">2</li>
<li id="item-3">3</li>
<li id="item-4">4</li>
<li id="item-5">5</li>
</ul>
And need to get index of a specific item disregarding hidden items.
var list = document.getElementById('list');
var items = list.querySelectorAll('li:not([style*="display: none"])');
I try to convert NodeList in Array:
var list_items = Array.from(items);
But don't known how to run something like that: list_items.indexOf('item-3')
https://codepen.io/marcelo-villela-gusm-o/pen/RwNEVVB?editors=1010
You can make a function to find the id you need in a list you want, passing two parameters, that way you can use this function dynamically.
Based on id, inside the function just need to use .findIndex() that returns the index or -1 if not found.
See here:
var list = document.getElementById('list');
var items = list.querySelectorAll('li:not([style*="display: none"])');
var list_items = Array.from(items);
function getIndexById(idToSearch, list){
//ES6 arrow function syntax
return list.findIndex(elem => elem.id == idToSearch)
//normal syntax
//return list.findIndex(function(elem) {return elem.id == idToSearch})
}
console.log("found at index: ", getIndexById("item-3", list_items))
<ul id="list">
<li id="item-1">1</li>
<li id="item-2" style="display: none">2</li>
<li id="item-3">3</li>
<li id="item-4">4</li>
<li id="item-5">5</li>
</ul>
Not exactly related to the question, but if possible, I would suggest you to change your HTML to remove that inline style of display: none and change it to a class, (e.g: class='hidden'), it would be better for your .querySelector when using :not, for example: li:not(.hidden), since any space in your inline style can break your selector. ("display:none" != "display: none", spot the space)
Maybe like this:
var item = list_items.find(function(item) {
return item.id === "item-3";
});
I would recommend using :not(.hidden) instead of "grepping" for a match on the style tag. Then, simply find the index after casting the NodeList to an array.
For the Vue.js inclined, see this fiddle: https://jsfiddle.net/634ojdq0/
let items = [...document.querySelectorAll('#list li:not(.hidden)')]
let index = items.findIndex(item => item.id == 'item-4')
console.log('item-4 index in visible list is', index)
.hidden {
display: none;
}
<ul id="list">
<li id="item-1">1</li>
<li id="item-2" class="hidden">2</li>
<li id="item-3">3</li>
<li id="item-4">4</li>
<li id="item-5">5</li>
</ul>
Maybe you can use map. First you can create an object with id and value. Then use map function to create array of this object. Then you can access it with foreach, when id = 'item-3'.

Get `li` elements and push it into object

I have a simple question!
I have this html and js:
<ul>
<li id="x">foo</li>
<li id="y">bar</li>
</ul>
var data = {
'language': 'fa',
'phrases': {},
};
I want to append all li in the phrases of data for have this output:
{"language":"fa","phrases":{"x":"foo","y":"bar"}}
I try this:
data.phrases.$(this).attr('id') = $(this).html();
And try push this:
data.phrases.push( {$(this).attr('id') : $(this).html()} );
And try extend this:
data.phrases.extend( {$(this).attr('id') : $(this).html()} );
But does not work!
Completed code:
<ul>
<li id="x">foo</li>
<li id="y">bar</li>
</ul>
<div id="result"></div>
var data = {
'language': 'fa',
'phrases': {},
};
//I want to append all `li` in the `phrases` of `data` for have this output:
//{"language":"fa","phrases":{"x":"foo","y":"bar"}}
$("li").each(function() {
//data.phrases.$(this).attr('id') = $(this).html();
//data.phrases.push( {$(this).attr('id') : $(this).html()} );
//data.phrases.extend( {$(this).attr('id') : $(this).html()} );
});
$("#result").html(JSON.stringify( data ));
See here online code: https://jsfiddle.net/NabiKAZ/fw63jd5k/
You cannot .push() into Object.
Use assignment to properties instead:
var data = {
'language': 'fa',
'phrases': {},
};
$("li").text(function(i, txt) {
data.phrases[this.id] = txt;
});
$("#result").html(JSON.stringify( data ));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="x">foo</li>
<li id="y">bar</li>
</ul>
<div id="result"></div>
data.phrases is your object literal
[this.id] is your new object property, where this.id is the current li's ID
= txt; is where you assign to that property the value of the current li text
As you can figure out from above, if you need the entire HTML use .html() instead like:
$("li").html(function(i, html) {
data.phrases[this.id] = html;
});
You're quite close! The issue is that the dot operator in JavaScript cannot be used to evaluate a key then access it. You're looking for the [ ] operator, which can be used to evaluate whatever is in the brackets, then use the value as the key. So try this:
data.phrases[$(this).attr('id')] = $(this).html();
you have the right idea, but you aren't quite using your functions correctly. push is an array method, and extend just isn't a native method. so what we want to do is set the id to the key, and the value to the html
https://jsfiddle.net/fw63jd5k/2/
$("li").each(function(i, el) {
data.phrases[el.id] = $(el).html()
}

JQuery find all elements with a class add their id to a coma separated list

As the title says I want to find all li tags inside an ordered list called #selectable with the class .ui-selected and add their id's to a string with each id separated by a comma.
Here's an example of what my html looks like:
<ol id="selectable">
<li id="1" class="ui-selected"><li>
<li id="2"><li>
<li id="3" class="ui-selected"><li>
<li id="4"><li>
<li id="5" class="ui-selected"><li>
</ol>
Try this:
var selectedIds = $('#selectable .ui-selected').map(function() {
return this.id;
}).get().join(',');
Example fiddle
Was working with my fiddle and couldn't figure out why my test array was returning 10 items in stead of 5. You are not closing your list items use <li></li> in stead of <li><li>.
Your source was missing a /.
I pushed them in an array and converted the array to a string with toString()
var listItems = [];
$('#selectable .ui-selected').each(function(){
var theID = $(this).attr('id');
listItems.push(theID);
});
listItems = listItems.toString();
console.log(listItems);
http://jsfiddle.net/h6G8H/4/

How to remove a list element containing a particular link attribute from an unordered list

I have this unordered list and would like to get the data-file attribute value of a link element inside the list element of the unordered list, then delete the whole list element in which it lies if it is not in array z.
<ul id="hithere"class="image-list">
<li class='image-list'>
<div class='controls'>
<a href='#' class='image-list' data-name='myname'><img src='stop.png' ></a>
</div>
<span class='name'>myname12</span
</li>
<li class='image-list'>
<div class='controls'>
<a href='#' class='image-list' data-name='myname2'><img src='stop.png' ></a>
</div>
<span class='name'>myname1312</span
</li>
</ul>
And this is my jQuery but it deletes all the list elements
var z = ["myname", "yourname"];
$("li.image-list a.image-list ").filter(function () {
if ($.inArray($(this).attr('data-name'), z) == -1) {
$(this).parent("li.image-list").empty().remove();
}
});
here is the code recieving from server:
var box = $('#drone');
box.f_drop({
url: 't_file.php',
check_data:function(i,file,response){
z=[];z.push(response.Oname);
$("li.image-list ").filter( function () {
return $.inArray($(this).find('a[data-name]').attr('data-name'), z) == -1
}).remove();
},
});
why is it that all the lists are now being removed instead of just one ie the one not in array?? Also, how can i rename the data-name attribute,to say "xyz" instead.
There are few problems in your script
The array is called z not _out
The anchor element does not have a class
the data property is called name, not filename
Try
var z = ["myname", "yourname"];
$("li.image-list").filter(function () {
return $.inArray($(this).find('a[data-name]').attr('data-name'), z) == -1
}).remove();
Demo: Fiddle

Categories

Resources