Get `li` elements and push it into object - javascript

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()
}

Related

JQuery Append removing characters in IE and Edge

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!

pass color from view to jquery

Hi guys i have a view where i have some tags and that tags has a color, i cant change that color via css directly cause its a pseudo element .tag::after what i need is pass that value#tag.color` to the script but i have no idea how to do it i know that when i already did it i can change it easy with the hover and the css change via jquery but how can i pass the value?
#foreach (var tags in i.Tags)
{
<div class="col-md-2">
<ul class="tagMargin">
<li>#tags.NomeTag</li>
</ul>
</div>
}
You can use JQuery .data() and store arbitrary data associated with the matched elements
Having recreated a simple controller
public ActionResult Index()
{
var sampleList = new List<SampleModel>();
sampleList.Add(new SampleModel
{
Color = "#2ecc71",
Name = "Emerald"
});
sampleList.Add(new SampleModel
{
Color = "#2980b9",
Name = "Belize Hole"
});
sampleList.Add(new SampleModel
{
Color = "#c0392b",
Name = "Pomegranate"
});
return View(sampleList.ToList());
}
And the view with my data attribute
#foreach(var tags in Model)
{
<div>
<ul>
<li>#tags.Name</li>
</ul>
</div>
}
Simply retrieve the values of the attribute using JQuery by looping through the list items with the class .tag
var array = [];
$('.tag').each(function () {
array.push($(this).data('color'));
})
console.log(array);
Results:
["#2ecc71", "#2980b9", "#c0392b"]

Protractor AngularJS count, copy, and verify a list span

I am new to automated testing, Protractor, and angularJS. I have a list that I would like to count, copy to an array maybe, and verify the list text is present. For example The list shows Attractions, Capacity, and Content to the user so they know what privileges they have.
Below is the .html
<div class="home-info">
<div class="home-top home-section">
<h3>User Information</h3>
<div class="home-box">
<div class="property-group wide">
<span>
Change Phillips<br />
</span>
</div>
</div>
<div class="home-box">
<div class="property-group wide">
<div>Editors:</div>
<span>
<ul class="property-stack">
<li><span>Attractions</span>
</li>
<li><span>Capacity</span>
</li>
<li><span>Content</span>
</li>
<li><span>Media</span>
</li>
<li><span>Options</span>
</li>
<li></li>
<li></li>
<li><span>Upload CADs</span>
</li>
</ul>
</span>
</div>
</div>
</div>
Below is the code I have written. I can get the first item on the list however using .all isn't working for me.
var text = "";
browser.driver.findElement.all(By.xpath("//li/span")).count().then(function(count) {
initialCount = count;
console.log(initialCount);
});
browser.driver.findElement(By.xpath("//li/span")).getText().then(function(text) {
console.log(text);
});
I'm trying to avoid using xpath as I was told to try and avoid. To be honest Im lost. Thanks for the help in advance.
Code used for matching:
expect(myLists).toEqual(['Attractions', 'Capacity', 'Conent',
'Media', 'Options', 'Upload CADs'
]);
I am not sure what version of protractor you're using but you should be able to just call element without the browser or driver prefix. Using element.all should get you the array of of elements you're looking for.
If you want to access specific indexes within that array you can use the .get(index) suffix to the element.all
So below:
1. you get the array of the elements
2. you get the count of the array
3. we call a for loop to iterate through all the indexes of the array
4. each index of the array we call the getText() and print it to the console
var j = 0; // using this since the i iterator in the for loop doesn't work within a then function
var textList = [];
var text = "";
var myLists = element.all(by.css("li span"));
myLists.count().then(function(count) {
console.log(count);
for(int i = 0; i < count; i++){
myLists.get(i).getText().then(function(text) {
textList[j++] = text;
console.log(text);
});
}
});
EDIT:
In researching I actually found another way to iterate through the array of elements by using the .each() suffix to the element.all.
var j = 0; // using this since the i iterator in the for loop doesn't work within a then function
var textList = [];
var text = "";
var myLists = element.all(by.css("li span"));
myLists.count().then(function(count) {
console.log(count);
myLists.each(function(element, index) {
element.getText().then(function (text) {
textList[j++] = text;
console.log(index, text);
});
});
});
you should be able to use the textList array to match things.
expect(textList).toEqual(['Attractions', 'Capacity', 'Conent',
'Media', 'Options', 'Upload CADs'
]);

Collect all data attributes?

My webpage is dynamically generated with, data-runway-link, data-video-link, data-backstage-link, there will be more in the future.....
The patterns are always like this data-xxx-link, what I want to do are, extract the "xxx" text in each of them store them inside an array so that I can refer each of the info using javascript
<li> <a data-season="Designer Profiles" data--link="123" data-video-link="1233"> </a></li>
<li> <a data-season="Spring/Summer 2014" data-Runway-link="abc" data-video-link="abc"> 3.1 Phillip Lim</a></li>
<li> <a data-season="Spring/Summer 2014" data-Runway-link="abc" data-video-link="abc"> Acne Studios</a></li>
<li> <a data-season="Spring/Summer 2014" data-Runway-link="abc" data-video-link="abc"> Aigner</a></li>
<li> <a data-season="Spring/Summer 2014" data-Backstage-link="abc" data-video-link="abc"> Alexander McQueen</a></li>
<li> <a data-season="Spring/Summer 2014" data-Runway-link="abc" data-video-link="abc"> Alexander Wang</a></li>
$('a').each(function(){
console.log($(this).data())
})
result will look like:
{season: 'Designer Profiles', 'runwayLink':'abc' ...}
fiddle:
http://jsfiddle.net/acrashik/NnHqQ/5/
STEP2: removing word link from keys
easiest way would be:
function removeLiknfromKey(data) {
var jsonstr = JSON.stringify(data);
var new_jsonstr = jsonstr.replace(/Link":/g, '":');
var new_obj = JSON.parse(new_jsonstr);
return new_obj;
}
you will have an object with XXX names only.
fiddle:
http://jsfiddle.net/acrashik/NnHqQ/6/
now you can use it nicely, using only name:
data.runway, data.video, data.season ... etc
When you access an element that has any data-* attributes with jQuery, you can access an object containing all of the data-* elements using the data() function.
For example, if you had an element like this:
<a id="elem" data-season="Designer Profiles" data-link="123" data-video-link="1233"> </a>
You could do something like this:
var element_data = $( "#elem" ).data();
Now, each of the keys within element_data will have each data attribute.
element_data[ "season" ]; // "Designer Profiles";
element_data[ "link" ]; // "123";
element_data[ "video-link" ]; // "1233";
Here is the relevant documentation for the data() function: http://api.jquery.com/data/
As you can see, the same function acts as a getter and a setter function. So to retrieve a specific key of data you would do something like this:
var video_link = $( "#elem" ).data( "video-link" ); // "1233"
You could also set the video-link value:
var new_video_link_value = "some other value";
var video_link = $( "#elem" ).data( "video-link", new_video_link_value );
To put all of this to use and to answer your question, what you would do is something like this:
var elems = $("li > a"); // extract all of the relevant anchor tags
var elem_data = [];
$.each( elems, function( index, elem ){
elem_data.push( $(elem).data() );
});
You will now have all of the data attributes for each anchor tag within the elem_data array. What might be a better idea is to give each anchor tag some sort of identifier so that you can map the data back to the relevant element that it came from.
Try this:
$('li a').each(function(){
console.log($(this).data())
});

How to check element does exist after mustache templating

I have this mustache setup:
$.getJSON('data/data.json', function(data) {
var template = "<ul>{{#"+elements+"}}<li class=\"selector {{.}}\"></li>{{/"+elements+"}}</ul>";
var html = Mustache.to_html(template, data);
panel.html(html);
});
After this I need to add some action on my <li> element with class selector. But there is a little problem with this element rendering to DOM. So I use small function to check this element does exist, but something is wrong and I have no results...
$.fn.doesExist = function(){
return $(this).length > 0;
};
var picker = $('li.selector');
if (picker.doesExist()) {
$(this).click(function(){
console.log('log');
})
}
and my html:
<div class="panel">
<ul>
<li class="selector 01"></li>
<li class="selector 02"></li>
<li class="selector 03"></li>
</ul>
</div>
Try this :
$.getJSON('data/data.json', function(data) {
var template = "<ul>{{#"+elements+"}}<li class=\"selector {{.}}\"></li>{{/"+elements+"}}</ul>";
var html = Mustache.to_html(template, data);
panel.html(html);
//*******************
// PERFORM TEST HERE
//*******************
});
//*******************
// $.getJSON() is asynchronous so
// performing test here is too early.
// The response from the server is guaranteed
// not to have arrived yet.
//*******************
try with
if($('li.selector').length>0){
$('li.selector').click(function(){
alert("wow")
})
}
jsFiddle

Categories

Resources