Loop through a set of ids and copy them - javascript

I have an unordered list with ids like so:
<li id="e1">01</li>
<li id="e2">02</li>
<li id="e3">03</li>
<li id="e4" class="event_day">04</li>
<li id="e5" class="event_day">05</li>
And a div with content like so:
<div id="descriptions">
<div></div>
<div></div>
</div>
I want to copy the ids of the list items with the class event_day and assign them to the divs with a letter at the end so that they would become:
<div id="e4d"></div>
<div id="e5d"></div>
I have come up with:
$("#descriptions>div").each(function() {
$(this).attr("id", $(".event_day").attr("id") + "d");
});
But as you can probably tell, it does not loop and rather takes the first id and assigns it to all the divs resulting in:
<div id="e4d"></div>
<div id="e4d"></div>
I'd highly appreciate it if you could explain the flaw in the logic and maybe even a link to something that I could read to improve my skills. I was looking at http://docs.jquery.com/Attributes/attr#keyfn but it did not make sense. Thanks for reading!

the each function from jquery also passes an index parameter to the callback function.
Provided that the amount of divs in descriptions is the same as the divs with class event_day:
$("#descriptions>div").each(function(n) {
$(this).attr("id", $(".event_day").eq(n).attr("id") + "d");
});
.eq(n) returns the element at position N in the jquery resulset.
Your query could be a little bit more efficient though because now you traverse the dom for each div in descriptions. Better (imho) would be:
var event_days = $("#listIdentifier .event_day");
$("#descriptions>div").each(function(n) {
$(this).attr("id", event_days.eq(n).attr("id") + "d");
});

It may be easier to collect all IDs of event days, then create divs dynamically with the IDs you want as needed.
$("li.event_day").each(function() {
$("#descriptions").append(
$("<div>").attr("id", $(this).attr("id") + "d")
);
});

Could you determine what you need before you render the HTML, and then just draw both the list and the divs accordingly?
<?php
$event_days = array(4,5);
$list = '<ol>';
$divs = '';
for($i=1;$i<30;$i++)
{
// built the list
$list .= '<li id="e'.$i.'" ';
if(in_array($i, $event_days))
{
$list .= 'class="event_day"';
}
$list .= '>Day '.$i.'</li>';
// build the divs
if(in_array($i, $event_day)
{
$divs .= '<div id="e'.$i.'d"></div>';
}
}
$list .= '</ol>';
echo $list;
echo $divs;
?>

The flaw in your logic is that your only matching the first element, which is e4.
So, just create an array and add the ids that match the class event_day:
var myIds=new Array();
$("li.event_day").each(function() {
myIds.push($(this).attr("id") + "d");
});
Then loop through the divs within the description div and set their ids like this:
var count = 0;
$("#descriptions>div").each(function() {
$(this).attr("id", myIds[count]);
count = count + 1;
});

Related

change the div color when function called - jquery

here is the list of products are printed using while loop
while($rr = $retval->fetch_object()) {
$summery_return .= '<div class="w3-blue w3-card-4" style="font-size:18px;">';
$summery_return .= '<span style="color:white;padding:2px;font-weight:bold" id="itmslct" data-proname='.$rr->product.'>'.$rr->product.'<span style="float:right;margin-right:19px;">'.$rr->qty.'</span>';
$summery_return .='</span><hr style="margin:3px"></div>';
}
script
$summery_return .='<script>
$(document).ready(function(){
$("#itmslct").click(function() {
var loc_proname = $(this).attr("data-proname");
alert(loc_proname);
$("."+loc_proname).css("background-color", "#f00");
});
});
</script>';
return $summery_return;
products in table
while($row = $result2->fetch_object()){
$icost=$row->quantity*$row->price;
$progress_return .='<tr class='.$row->product.'>
<td><b>'.$row->product.'</b></td>
<td><b>'.$row->type.'</b></td>
<td><b>'.$row->quantity.'</b></td>
<td><b>'.$row->pack.'</b></td>
<td><b>'.$row->topping.'</b></td>
<td><b>'.$row->extra.'</b></td>
<td><b>'.$row->comments.'</b></td>
<td><button style="background-color:red;color:white">Done</button></td>
</tr>';
$total=$total+$row->quantity*$row->price;
}
when i click on the product which is printed by first while loop then the background color of products in 2nd while loop should change.
There are multiple products in table with same name, all there background color need to be changed when i select the product on first while loop
i tried doing it but i don't see any results
I guess your code is not working because your HTML is not valid. In DOM; id should be unique. So to avoid duplicate ids; please modify PHP as well as corresponding JS code. Instead of id="itmslct" we will make it class as follows:
while($rr = $retval->fetch_object()) {
$summery_return .= '<div class="w3-blue w3-card-4" style="font-size:18px;">';
$summery_return .= '<span style="color:white;padding:2px;font-weight:bold" class="itmslct" data-proname='.$rr->product.'>'.$rr->product.'<span style="float:right;margin-right:19px;">'.$rr->qty.'</span>';
$summery_return .='</span><hr style="margin:3px"></div>';
}
And associated JS would be:
$(document).ready(function(){
$(".itmslct").click(function() {
var loc_proname = $(this).attr("data-proname");
alert(loc_proname);
$("."+loc_proname).css("background-color", "#f00");
});
});
ids should be unique. You should use a class instead.
Also, it appears you're setting the background color of a tr.
Try styling the td cells instead.
Either target them with the selector
$("."+loc_proname + ' td')
or add the class to the td elements.
I would recommend the second option as styling specific element selectors doesn't scale well in your styles.

Jquery looped array selectors with custom element ID's

Going through the other posts i must either have something wrong with my code or my logic is fundamentally flawed.
So what happens is i have a series of array elements that get called/written, these array elements need to have sub elements modified by java script.
Everything was workign before i needed to add an array i.e i was using a single element selector ID for the functions below and got the correct results. However after adding unique ID's in a loop it doesn't want to change.
So here's what happens, I have a separate div that is hidden. This prints out how many elements are in the array as its a PHP session variable. $Carray is a count function and works correctly.
<div class="Carray"><?php echo $Carray;?></div>
Then as the items are looped they add an array ID
<?php
$arrayID = -1;
foreach($_SESSION['activity'] as $key){
foreach($key as $list){
$arrayID += 1;
?>
<div id="subP_<?php echo $arrayID;?>" class="booking_action">-</div>
<div id="booking_people_<?php echo $arrayID;?>" class="booking_people_number">
<?php echo $list["i_quantity"] ?>
</div>
<div id="addP_<?php echo $arrayID;?>" class="booking_action">+</div>
<?php }} ?>
Then in Javascript i call a loop function that counts through however many $Carray elements there are and then corresponds the correct function actions to the correct div ID's
//get the counted array variable and force as an int
var js_var = parseInt($('.Carray').html(),10);
// loop for however many array elements there are
for (i = 0; i < js_var; i++){
// get the amount of people from a field
var ppl_P = parseInt($('#booking_people_'+i).html(),10);
// subtract 1 person and then change the output to match the new people count
$("#subP_"+i).click(function() {
if(ppl_P >= 2){
ppl_P -= 1;
$('#booking_people_'+i]).html(ppl_P);
}
});
// Add 1 person and then change the output to match the new people count
$("#addP_"+i).click(function() {
ppl_P += 1;
$('#booking_people_'+i).html(ppl_P);
});
}
****************************** EDIT **********************
So based on Jimmi Elofsson answer which works beautifully, i want to expand this to effect elements that are not inside the parent/child selectors. The selector is '.booking_price_inner' which is another div stored elsewhere. I am assuming the line that needs the correct syntax is the marked line.
The '.booking_base_price' is within the parent/child element.
$(".subPerson").click(function() {
// Subtract Person
var subPeopleCount = getCurrentCountByPeopleItem($(this).parent()) - 1;
$(this).parent().children('.booking_people_number').html(subPeopleCount>1 ? subPeopleCount : 1);
//Change price
var totalPriceS = subPeopleCount * getBasePrice($(this).parent());
$(this).parent().children('.booking_price_inner').html(totalPriceS); <-------
});
$(".addPerson").click(function() {
//Add person
var addPeopeCount = getCurrentCountByPeopleItem($(this).parent()) + 1;
$(this).parent().children('.booking_people_number').html(addPeopeCount);
//Change price
var totalPriceA = addPeopleCount * getBasePrice($(this).parent());
$(this).parent().children('.booking_price_inner').html(totalPriceA); <------
});
// get the number of people in the specific array
function getCurrentCountByPeopleItem(peopleItem) {
return parseInt(peopleItem.children('.booking_people_number').html());
}
//get the base price
function getBasePrice(peoplePrice){
return parseInt(peoplePrice.children('.booking_base_price').html());
}
Markup
<div id="<?php echo $arrayID;?>" class="booking_people">
<div class="booking_date_header">People:</div>
<div class="subPerson booking_action">-</div>
<div class="booking_people_number"><?php echo $list["i_quantity"] ?></div>
<div class="addPerson booking_action">+</div>
<div class="booking_base_price"><?php echo $list["i_base_price"] ?></div>
</div>
<div class=spacer></div>
<div class=cost>
<div class=booking_price_inner></div>
</div>
If you don't mind, I did some changes in your code.
you could make your add/substract element use the same click function with the help of some DOM traversing. That way you wouldnt need the CArray to keep track of the buttons.
Javascript:
// subtract 1 person and then change the output to match the new people count
$(".subPerson").click(function() {
var subPeopleCount = getCurrentCountByPeopleItem($(this).parent()) - 1;// Substract by one.
$(this).parent().children('.booking_people_number').html(subPeopleCount>1 ? subPeopleCount : 1);
});
// Add 1 person and then change the output to match the new people count
$(".addPerson").click(function() {
var addPeopeCount = getCurrentCountByPeopleItem($(this).parent()) + 1; // Increase by one.
$(this).parent().children('.booking_people_number').html(addPeopeCount);
});
function getCurrentCountByPeopleItem(peopleItem) {
return parseInt(peopleItem.children('.booking_people_number').html());
}
PHP:
<?php
$arrayID = -1;
foreach($_SESSION['activity'] as $key){
foreach($key as $list){
$arrayID += 1;
?>
<div class="booking_people_item" id="<?php echo $arrayID;?>">
<div class="subPerson booking_action">-</div>
<div class="booking_people_number">
<?php echo $list["i_quantity"] ?>
</div>
<div class="addPerson booking_action">+</div>
</div>
<?php }} ?>
I added a div wrapper around your elements called booking_people_item.
from what I see - you're definig click functions in a loop. Those click functions have a reference to a ppl_P variable. When you define the click, it seems OK. But when the click is triggered, the ppl_P variable is already set to the value from loops last iteration. So, whenever you call that click function, it always has the same result, doesn't it?
The proper way to do it would be to pass this ppl_P variable as a parameter, so you don't have a reference to a variable that was already changed in the other scope. Something like:
function addClickFunction(i, ppl_P){
$("#subP_"+i).click(function() {
if(ppl_P >= 2){
ppl_P -= 1;
$('#booking_people_'+i]).html(ppl_P);
}
});
// Add 1 person and then change the output to match the new people count
$("#addP_"+i).click(function() {
ppl_P += 1;
$('#booking_people_'+i).html(ppl_P);
});
}
And then use this function inside the loop:
var ppl;
for (i = 0; i < js_var; i++){
ppl = parseInt($('#booking_people_'+i).html(),10);
addClickFunction(i, ppl);
}
This hasn't been tested, but I'm pretty sure you'll get the point :)

Zclip not working

Hi friends I am trying to implement click to copy using zclip.
I am having different ids for same class so initially i am finding the id of the element on which i clicked and applying zclip to that element.
$(".coupon_code_text").on('click', function (e) {
pos = "#" + $(this).attr("id");
e.preventDefault();
clktocpy();
function clktocpy(){
$(pos).zclip({
path: 'http://www.steamdev.com/zclip/js/ZeroClipboard.swf',
copy: function () {
return $(pos).text();
}
});
}
})
The following is the php part where I am generating different ids for the same class.
<?php
$count = 0;
foreach($coupons as $value)
{
$count = $count +1;
<div class="coupon_code" >
<a class="coupon_code_text" id ="copypath-<?php echo $count;?>">
<?php echo $array['coupon_code'];?>
</a>
</div>
<?php}?>
Remember that in order to get by id using jQuery you need to append a # to the string.
Like the following #myId, your variable pos only contains the id without the #.
Line 2, fixed
pos = "#" + $(this).attr("id");

JQuery find child element inner text and replace with IMG HTML

I need a little help with a Javascript function I am creating. In essence, I need to loop through a set of DIVs with class .DetailRow and find a child DIV's content (inner text). If this text is matched to a variable, then I need to replace this inner text with an IMG HTML statement.
BTW I am kinda new at this (4 months old!) so apologies if the issue is simple, but I have tried a few combos and I am stuck.
Here's the HTML:
<div class="DetailRow" style="display: ">..</div>
<div class="DetailRow" style="display: ">..</div>
<div class="DetailRow" style="display: ">
<div class="Label">Availability:</div>
<div class="Value">in stock + Free Shipping</div>
</div>
Example, if I find "in stock" in the LABEL inner text, I want to replace it with the value of the variable "instock" which is an IMG HTML statement. See my code attempt below.
<script type="text/javascript">
$(window).load(function(){
var instock = '<img src="https://linktoimgfolder/instock.gif" title="Product available, usually ships 24hrs to 48hrs after order receipt" style="margin-top:-3px;">';
var lowstock = '<img src="https://linktoimgfolder/lowstock.gif" title="Product stcok low, order today so you do not miss out">';
var nostock = '<img src="https://linktoimgfolder/outstock.gif" title="Product out of stock, could ship 1 to 2 weeks after order receipt">';
$('div.DetailRow')each(function(){
if (indexOf($(this).childNodes[1].innerHTML, "in stock") > 0) {
$(this).childNodes[2].innerHTML = "";
$(this).childNodes[2].innerHTML = instock;
} else if (indexOf($(this).childNodes[1].innerHTML, "low stock") > 0) {
$(this).childNodes[2].innerHTML = "";
$(this).childNodes[2].innerHTML = lowstock;
} else {
$(this).childNodes[2].innerHTML = "";
$(this).childNodes[2].innerHTML = nostock;
};
});
});
</script>​
By the way,m I cannot match text exactly as the text beyond the "+" will change from time to time, thus I am trying indexOf.
Many thanks in advance for your assistance!
M
Using the :contains selector
var stock = {'in stock': instock, 'low stock': lowstock, 'no stock': nostock};
Object.keys(stock).forEach(function(key) {
$('div.DetailRow div:contains(' + key + ')').html(stock[key]);
});
jsFiddle Demo
A pure jQuery solution:
$.each(stock, function(key, value) {
$('div.DetailRow div:contains(' + key + ')').html(value);
});
You have typo in this line $('div.DetailRow')each(function(){ and then you can use jQuery .text() and .html() to check value and update.
Try:
$('div.DetailRow').find("div").each(function(){
if($(this).text().indexOf("in stock")!=-1){
$(this).text("");
$(this).html(instock);
}else if($(this).text().indexOf("low stock")!=-1){
$(this).text("");
$(this).html(lowstock);
}else{
$(this).text("");
$(this).html(nostock);
}
});
DEMO FIDDLE
NOTE: Updated code to find div inside div.DetailsRow. Change it according to your requirement.

how to appending content from array and then clear it in jQuery

Hi i would like to create an array from the title and src of an image set. Then append it to a list, then clear the array (the images in the set changes) then clear the array and the list. repeat it again and again as the images change in the set.
Here is the HTML:
<div id="imageholder">
<img src="images/a001.png" title="orange"/>
<img src="images/a002.png" title="red apple"/>
<img src="images/a003.png" title="green apple"/>
<img src="images/a004.png" title="red apple"/>
</div>
<ul id="list"></ul>
and here is the code:
title_array = [];
src_array = [];
function sumarychange() {
$("#imageholder img").each(function() {
// pushing each values into arrays
title_array.push($(this).attr("title"));
src_array.push($(this).attr("src"));
// i think this part will append the content in the arrays
var list = $('#list');
var existing_item = $('#list_'+ title);
// removing items with the same titles
if (existing_item.length < 1){
var new_item = $('<li />');
new_item.attr('id', 'list_'+ title);
new_item.html('<div>' + title + '</div><img src="' + src + '" />');
list.append(new_item);
}
});
// i think this will set the arrays back to empty
title_array.length = 0;
src_array.length = 0;
}
this is just a sample. In actual the image has more tags. i have no clue how to empty out the list when this function is called again. im just learning coding now and i have no idea how to correct this to make it work.
This looks to me like an XY problem.
Judging from your example code above as well as your previous question, I'm guessing what you're trying to do is update a list of entries based on the attributes of an existing set of elements, but with items with duplicate titles only displayed once.
Assuming I got that right, here's one way to do it: (demo: http://jsfiddle.net/SxZhG/2/)
var $imgs = $("#imageholder"), $list = $("#list");
function summary_change() {
// store data in tmp obj with title as key so we can easily ignore dups
var store = {};
$imgs.find("img").each(function() {
if (store.hasOwnProperty(this.title)) return; // ignore dup title
store[this.title] = this.getAttribute("src");
});
$list.empty(); // empty the list
for (var title in store) { // add new list items
$("<li>")
.append($("<div>", {"text":title}))
.append($("<img>", {"src":store[title]}))
.appendTo($list);
}
}
Note that if more than one image has the same title, only the src of the first one is used in the summary results. If you wish to use the src of the last item found, simple remove the line if (store.hasOwnProperty(this.title)) return;.

Categories