Loop in jquery based on razor loop - javascript

I have a for each loop in my razor view (MVC4)
#foreach (var fe in ViewBag.FeatureProducts)
{
<div class="product-details" style="display:none;">#Html.Raw(fe.Details)</div>
<div class="product-qty-dt"> </div>
}
in the each loop i have to extract the #html row content and display in to the div 'product-qty-dt'.
For that I write the following jquery,
$(document).ready(function () {
var data = $('.product-details p').map(function () {
return $(this).text();
}).get();
//product availability
var availability = data[2].split(",");
$.each(availability, function (i) {
$('.product-qty-dt').append( availability[i])
});
});
But this was only consider the last foreach raw. how can i call this jquery in each loop call.
For example, In first loop,
<div class="product-details" style="display:none;"><p>Lorem, Ispum</p><p>doler emit,fghjh</p><p>9gm</p></div>
<div class="product-qty-dt"> 9gm </div>
second loop
<div class="product-details" style="display:none;"><p>Lorem, Ispum</p><p>doler emit,fghjh</p><p>5gm</p></div>
<div class="product-qty-dt"> 5gm </div>
Thirdloop
<div class="product-details" style="display:none;"><p>Lorem, Ispum</p><p>doler emit,fghjh</p><p>3gm</p></div>
<div class="product-qty-dt"> 3gm </div>

The following will add the text of the last <p> in a <div class="product-details"> element into the corresponding <div class="product-qty-dt"> element
$('.product-details').each(function () {
var t = $(this).children('p').last().text();
$(this).next('.product-qty-dt').text(t);
})

This should do the trick. Also the data array is still used just incase you would like to access other data portions stored in product-details.
$(".product-details").each(function()
{
var data = $(this).find('p').map(function () { return $(this).text() }).get();
$(this).next('.product-qty-dt').text(data[2]);
})

Related

How to addEventListener and function with element as a parameter to multiple elements?

My goal is to have a bunch of div with clickable words to pass their ids to a Javascript function when one of them is clicked by the user. It works flawlessly for
<div id="wordbox">
<div id="pd"><h4>pdf</h4><br></div>
<div id="an"><h3>analysis</h3></div>
<div id="ai"><h2>artificial intelligence</h2></div>
<div id="tr"><h4>trends</h4><br><br></div>
<div id="dm"><h3>data mining</a></div>
</div>
var word = document.getElementById("pd");
word.addEventListener("click", function(){ showSlide(word.id) });
but I don't manage to get it working for all elements. This fails:
var wb = document.getElementById("wordbox").children;
wb.forEach(function (element, index){
element.addEventListener("click", function(){
showSlide(element.id);
});
});
Any ideas?
When you select the children from a node, it actually returns an array-like collection which is similar but not quite an array. In order to use forEach you first need to convert it into an array, and in the case below, I used the spread syntax to convert it into an array that allows me to use forEach.
const wb = document.querySelector('#wordbox')
const children = [...wb.children]
children.forEach(child => {
child.addEventListener('click', () => {
console.log(child.id)
})
})
<div id="wordbox">
<div id="pd"><h4>pdf</h4><br></div>
<div id="an"><h3>analysis</h3></div>
<div id="ai"><h2>artificial intelligence</h2></div>
<div id="tr"><h4>trends</h4><br><br></div>
<div id="dm"><h3>data mining</a></div>
</div>
wb is not a real array, it is an array-like object called live HTMLCollection. You can get an array using Array.from(). You can also use document.querySelectorAll() to select the elements
var wb = document.querySelectorAll("#wordbox > div");
// new browsers - https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#bcd:api.NodeList.forEach
// wb
// To support older browsers
Array.from(wb)
.forEach(function(element, index) {
element.addEventListener("click", function() {
console.log(element.id);
});
});
<div id="wordbox">
<div id="pd">
<h4>pdf</h4><br></div>
<div id="an">
<h3>analysis</h3>
</div>
<div id="ai">
<h2>artificial intelligence</h2>
</div>
<div id="tr">
<h4>trends</h4><br><br></div>
<div id="dm">
<h3>data mining</a>
</div>
</div>

jQuery iterate through elements within another element

I have HTML like this:
<div class="foo">
<div class="bar1">A</div>
<div class="bar2">B</div>
<div class="bar3">C</div>
</div>
<div class="foo">
<div class="bar1">D</div>
<div class="bar2">E</div>
<div class="bar3">F</div>
</div>
<div class="foo">
...etc.
I am trying to iterate through the "foo" divs to create objects like {bar1: A, bar2: B, bar3: C} with code sort of like this:
var arrayOfObjects= [];
var rows = $(".foo");
for (var i=0; i<rows.length; i++) {
var row = rows[i];
arrayOfObjects.push(
{
bar1: row.find(".bar1").text(),
bar2: row.find(".bar2").text(),
bar3: row.find(".bar3").text()
}
);
}
I understand that this doesn't work because the original var rows = $(".foo"); creates an array of DOM elements, which don't have find() as a function. I also know that within the loop, I could start using elementByClass and innerHtml, but I feel like my brain starts crying whenever I start mixing jQuery-style and DOM-style selectors in the same code.
Is there a way to fix my code above so that I'm using jQuery selectors within the loop?
You can wrap your elements as jQuery objectslike this:
arrayOfObjects.push(
{
bar1: $(row).find(".bar1").text(),
bar2: $(row).find(".bar2").text(),
bar3: $(row).find(".bar3").text()
}
);
This makes you row a JQuery object, which has the 'find' method.
You can easily iterate through .row divs by using each(),
var arrayOfObjects= [];
$(".foo").each(function(){
var items = {"bar1" : $(this).find('.bar1').text(),"bar2" : $(this).find('.bar2').text(), "bar3" : $(this).find('.bar3').text()};
arrayOfObjects.push(items); //If you want to push all into an object and then into an array
//or to use it on its own
$(this).find('.bar1').text();
$(this).find('.bar2').text();
$(this).find('.bar3').text();
});
Hope this helps.
//find all the foo, and map them into new elements
var result = $('.foo').map(function(index, element){
//we want to map all the children of the element into a single object
return $(element).children().get().reduce(function(aggregate, childElement){
//get the class off of the child and it's value, put them in the object
aggregate[childElement.className] = childElement.innerText;
return aggregate;
}, {}); //second argument to the reduce() is the starting element
}).get(); //use get() to break the array out of the jQuery object
console.log(result);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">
<div class="bar1">A</div>
<div class="bar2">B</div>
<div class="bar3">C</div>
</div>
<div class="foo">
<div class="bar1">D</div>
<div class="bar2">E</div>
<div class="bar3">F</div>
</div>
$(document).ready(() => {
var arrayOfObjects = $('.foo').map(function() {
return $(this).find('>*').map(function(obj) {
return {
class: $(this).attr('class'),
text: $(this).text()
};
}).get().reduce( (obj, arr) => {
obj[arr.class] = arr.text;
return obj;
}, {});
}).get();
console.log(arrayOfObjects);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">
<div class="bar1">A</div>
<div class="bar2">B</div>
<div class="bar3">C</div>
</div>
<div class="foo">
<div class="bar1">D</div>
<div class="bar2">E</div>
<div class="bar3">F</div>
</div>
hope this helps you :)
Something along these lines with .each would probably work
const $rows = $('.foo');
let arrayOfObjects = [];
$rows.each(function(i) {
const $row = $(this);
let obj = {};
$row.children().each(function(ch) {
obj = { ...obj, [this.className]: $(this).text() };
});
arrayOfObjects = [ ...arrayOfObjects, obj ];
});
console.log(arrayOfObjects);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="foo">
<div class="bar1">A</div>
<div class="bar2">B</div>
<div class="bar3">C</div>
</div>
<div class="foo">
<div class="bar1">D</div>
<div class="bar2">E</div>
<div class="bar3">F</div>
</div>

Including the current node in the find scope

Consider the following snippet as an example:
<div class="bar foo">
</div>
<div class="bar">
<div class="foo"></div>
</div>
Given var $set=$('.bar'); I need to select both nodes with foo class. What is the proper way to achieve this. Considering addBack() requires a selector and here we need to use the $set jQuery object and $set.find('.foo') does not select the first node.
use this :
var $set = $(".bar").filters(function () {
var $this = $(this);
if($this.is(".foo") || $this.find(" > .foo").length !== 0){
return true;
} else{
return false;
}
});
Here's one way of going about it:
var set = $('.bar');
var foos = [];
for (var i = 0; i < set.length; i++) {
if ($(set[i]).hasClass('foo')) {
foos.push(set[i]);
}
}
if (set.find('.foo').length !== 0) {
foos.push(set.find('.foo')[0]);
}
console.log(foos);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bar foo"></div>
<div class="bar">
<div class="foo"></div>
</div>
The for loop checks all elements picked up with jQuery's $('.bar'), and checks if they also have the foo class. If so, it appends them to the array. The if checks if any of the elements picked up in set have any children that have the foo class, and also adds them.
This creates an array that contains both of the DIVs with the foo class, while excluding the one with just bar.
Hope this helps :)
test this :
var $newSet = $set.filter(".foo").add($set.has(".foo"));
You could use the addBack() function
var $set=$('.bar');
console.log($set.find(".foo").addBack(".foo"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="bar foo">
</div>
<div class="bar">
<div class="foo"></div>
</div>

How to iterate through all div and get specific property?

what I'm trying to do is iterate over a collection of div, contained in a parent container. My structure is the following:
<div id='main'>
<div data-id='2'>
</div>
<div data-id='3'>
</div>
</div>
My goal is take the field data-id of each div and create an array collection. Previously I used the select where do I get each value of available option, like this:
var available_services = $('#selected-service').find('option', this).map(function ()
{
return this.value;
}).get();
But now I'm using a div collection instead of the select. How I can iterate through all available div?
This should return all data-id values in a list:
var available_services = $('#main').find('div').map(function (item)
{
return item.attr('data-id');
});
I didn't test this, but I think should do the job. (maybe you need to tweak a little bit)
I believe this will do it:
var available_services = [];
$('#main div').each(function(){
available_services.push($(this).data( "id" ));
})
This is the easy way to go:
$(document).ready(function() {
var myCollection = [];
$('#main div').each(function(){
var dataDiv = $(this).attr('data-id');
myCollection.push(dataDiv)
})
});
Try this:
(function(){
var main = $("#main");
var divs = $(main).find("div");
var arrId = divs.map(function(index, div){
return $(div).attr("data-id");
});
console.log(arrId);
})()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='main'>
<div data-id='2'>
</div>
<div data-id='3'>
</div>
</div>

Append script to ID using short code?

I have code like :
<div id="content">
<div id="widget1"></div>
<div id="widget89"></div>
<div id="widget78"></div>
..............
<div id="widget(anyIndex)"></div>
</div>
By adding content into widget (HTML/JS widget) I have :
<div id="content"
<div id="widget1">
<script type='text/javascript'>
jQuery("#widget1").selectme({
Numpost:4,
Stylepost:"papa",
});
</script>
</div>
<div id="widget89">
<script type='text/javascript'>
jQuery("#widget89").selectme({
Numpost:7,
Stylepost:"popo",
});
</script>
</div>
..............
<div id="widget(anyIndex)">.....</div>
</div>
It is so manual and time-consuming.
Now, I want use short code instead of repeating too much Javascript in each div like :
<div id="content"
<div id="widget1">[4][papa]</div>
<div id="widget89">[7][popo]</div>
..............
<div id="widget(anyIndex)">...</div>
</div>
JS :
<script>
(function (a) {
a.selectme = function (c, b) {
var d = this;
d.init = function () {
d.options = a.extend({}, a.selectme.defaultOptions, b);
...................something
};
d.init()
};
a.selectme.defaultOptions = {
Numpost:4,
Stylepost:"Enter your style",
};
a.fn.selectme = function (b) {
return this.each(function () {
(new a.selectme(this, b))
})
}
})(jQuery);
</script>
Notice :Widget(anyindex) is catch automatically. For example: widget89 is set current but I don't know the index of that widget (index = 89), just sure that I am inputting Javascript/Jquery code into it. When I add new widget I will have new index, for example : widget105 or also widget200 (anyindex)
How can I do that. Thanks for your help.
Here's a way using data attributes in markup and a simple each loop to initialize. Add data- attributes for the variables you need to specify in plugin.
<div id="widget89" data-numpost="7" data-style="popo">
alert( $('#widget89').data('numpost') );
To get index of widgets create a collection of them first to use to index against:
Using $.each to intialize the whole collection will give you the index of widget in collection ( I'm not clear what you need it for):
$('[id^=widget]').each(function(idx){
var $this=$(this), data=$this.data, INDEX=idx;
$this.selectme({
Numpost:data.numpost,
Stylepost:data.style
})
})
you can use a function
function setwidget(id,post,style)
{
jQuery("#"+id).selectme({
Numpost:post,
Stylepost:style
});
}
now call like
setwidget("widget1",4,"papa");
setwidget("widget89",7,"popo");

Categories