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 :)
Related
I have this code that loops through a HTML structure and builds an array based on its data attributes. I want to execute a conditional statement within a foreach loop and want to check if my count variable is within the array. I looked at inArray() but I'm not sure it works with associative arrays?
Here is the HTML
<div class="dfp" data-adposition="<?php echo $dfpPos; ?>" data-dfpcode='<?php echo $dfpCode; ?>'>
</div>
<div class="dfp" data-adposition="<?php echo $dfpHalfPos; ?>" data-dfpcode='<?php echo $dfpHalfCode; ?>'>
</div>
Here is the JS that builds the array.
var dfpObj = { "adverts" : [] };
$(".dfp").each(function(){ // PROCESS DFPS
var code = $(this).data("dfpcode");
var position = $(this).data("adposition");
var dfp = {
"code": code,
"position": position
}
dfpObj.adverts.push(dfp);
});
And my IF statement.
if($.inArray(count, dfpObj.adverts) !== -1) {
var dfp = $('.dfp[data-adposition=' + count + ']');
var dfpcode = $(dfp).data("dfpcode");
var dfppos = $(dfp).data("adposition");
myfunction(dfpcode, dfppos);
}
// count is within a foreach loop so at the end of the loop is $count++
You can use the following.
$.grep(dfpObj.adverts, function(obj) { return obj.code == "122"; })
This will give you that object or else gives you empty array.
im trying to pass a php array to javascript function onload that will display the js array in a drop down list but now im already doing it for sometime i guess i need to pop it again
first i pass it from one php file to another using this code
header("location: Rules.php?varFields=".serialize($varFields));
secondly i transfer to another variable as it had been passed to the said php file
<?php
$varArray = unserialize($_GET['varFields']);
?>
third part is im tyring to pass it into a jS functon that will then display it to a drop down list
<body id="body" onclick="cmbRuleField(\'' + <?php echo json_encode($varArray);?> + '\');" >
and here is the external javascript code
function cmbRuleField(varArray)//ruleField
{
var varDisplay = JSON.stringify(varArray);
var sel = document.getElementById("ruleField") // find the drop down
for (var i in varDisplay)
{ // loop through all elements
var opt = document.createElement("option"); // Create the new element
opt.value = varDisplay [i]; // set the value
opt.text = varDisplay [i]; // set the text
sel.appendChild(opt); // add it to the select
}
}
for the first two part i already tested it and it is working but for the last parts i cant make it work
I think this part looks suspicious
<body id="body" onclick="cmbRuleField(\'' + <?php echo json_encode($varArray);?> + '\');" >
maybe
<body id="body" onclick="cmbRuleField(<?php echo json_encode($varArray);?>)">
is more like it.
One more tip, you can see the output on the rendered page to determine what the written out code looks like. So if you see something like:
<body id="body" onclick="cmbRuleField('['a', 'b']')">
you know there is a problem. You want a native Javascript array to be passed like this
<body id="body" onclick="cmbRuleField(['a', 'b'])">
EDIT
After talking on chat it became clear the top portion of OP's code needed a tweak as well.
header("location: Rules.php?varFields=".http_build_query($varFields));
The problem has to do with quotes not being terminated here:
...
<body id="body" onclick="cmbRuleField(\'' + <?php echo json_encode($varArray);?> + '\');" >
...
The JSON created using json_encode will have a lot of double quotes. Try this:
<script>
var array = <?php echo json_encode($varArray);?>;
</script>
<body id="body" onclick="cmbRuleField(array);">
There is a much easier way. Encode the $varArray as direct HTML options before sending to the browser. For instance:
<select id="ruleField">
<?php for ($i = 0; $i < count($varArray); $i++) { ?>
<option value="<?php= $varArray[$i].val ?>"><?php= $varArray[$i].name ?></option>
<?php } ?>
</select>
Might be because you are calling JSON.stringify on something that is already a string?
Also what is myCars?
..
for (var i in myCars)
..
Possibly rename it to varArray.
or rename varDisplay to varArray.
and lastly try calling JSON.parse instead:
function cmbRuleField(varArray)//ruleField
{
var varDisplay = JSON.parse(varArray);
var sel = document.getElementById("ruleField") // find the drop down
for (var i in myCars)
{ // loop through all elements
var opt = document.createElement("option"); // Create the new element
opt.value = varDisplay [i]; // set the value
opt.text = varDisplay [i]; // set the text
sel.appendChild(opt); // add it to the select
}
}
If that didn't work post the html output here so peeps can create a fiddle :)
I am reposting this question with revised code that use more of jQuery.
Here is the HTML code that defines the objects:
<LEGEND><b>Select Study Sample</b></LEGEND>
<p>
<P CLASS=select_header>Study - Box - Well - Lab ID<br>
<SELECT multiple size=20 NAME="stylabid" ID="stylabid" onchange=show_stylabid() onclick=clear_fetch() STYLE="width: 115px">
<?php
$i=0;
while ($i < $numstylabids) {
$styarr = pg_fetch_row($stylabidresult);
echo "<option value=$styarr[0]>$styarr[1]\n";
$i++;
}
?>
</select>
and
<LEGEND><b>Select Project Sample</b></LEGEND>
<p>
<P CLASS=select_header>Project - Box - Well - Lab ID<br>
<SELECT multiple size=20 NAME="pjtlabid" ID="pjtlabid" onchange=show_pjtlabid() onclick=clear_fetch() STYLE="width: 115px">
<?php
$j=0;
while ($j < $numpjtlabids) {
$pjtarr = pg_fetch_row($pjtlabidresult);
echo "<option value=$pjtarr[0]>$pjtarr[1]\n";
$j++;
}
?>
</select>
Now, here is the javascript; I am simply trying to get the values of the selected object, which can be either a Study or a Project. I use this later to retrieve data from the database:
function fetchgenotype() {
var ms, mndx, ss, sndex = 0;
ms = $("#marker")[0].selectedIndex;
if (Study_selected) {
ss = $("#stylabid")[0].selectedIndex;
sndx = $("#stylabid").val(ss);
} else
ss = $("#pjtlabid")[0].selectedIndex;
sndx = $("#pjtlabid").val(ss);
}
// for debugging...
alert('ss='+ss+', sndx='+sndx);
This code dies on the line sndx = ... Would really appreciate any help!
TIA
Currently i don't know what $("#marker") an Study_selected are.
Assuming there is anything OK so far, change the function into:
if (Study_selected) {
sndx = $("#stylabid").val();
} else
sndx = $("#pjtlabid").val();
}
val() returns the value of a form-element when used without an argument, otherwise it will set the value and return an jQuery-object.
There is no need to retrieve the selectedIndex, you may access the value of the select-element directly(it will be the value of the currently selected option)
I think you have a syntax error
sndx should be sndex .. or the other way around
var ms, mndx, ss, sndex = 0; // <--
$("#pjtlabid").val(ss) // <-- setter method
.val(value) is also a setter method so sndx is undefined because it never was defined with any value
It's a typo:
var ms, mndx, ss, sndex = 0;
should be
var ms, mndx, ss, sndx = 0;
If I have a normal
<?php echo "Today (".mysql_num_rows($query)."); ?>
That turns out as Today (10) if there's 10 rows.
Now under this counter I have an while() that outputs all the rows inside a <tr>.
In a <td> inside the tr i have this delete button, which hides closest 'tr'.
How can I when you hide the 'tr' the Today(10) will decrease to Today(9) ?
--
I dont think its possible with the current counter (mysql_num_rows), but maybe if you count how many 'tr' there is, in the Today(), you could make something that decreases, but I do not know how to do this. Although this is just an thought..
Alter your PHP accordingly:
<?php echo 'Today (<span class="counter">' . mysql_num_rows($query) . '</span>)'; ?>
And have something like this for your delete button:
$('#theTable').delegate('button.delete', 'click', function (event) {
$(this).closest('tr').slideUp();
$('span.counter').text(function (index, val) {
return (parseInt(val, 10) - 1);
});
event.preventDefault();
});
Note the use of delegate: It's much more efficient than it would be to bind an event handler to each delete button.
You'll have to alter the selector for your table and your delete button accordingly.
you can do something like this :
$('.deleteButton').click(function() {
var curn = parseInt($('.counter').text(), 10);
if(curn - 1 >= 0)
$('.counter').text(curn - 1);
});
and change your echo to
<?php echo "Today (<span class='counter'>".mysql_num_rows($query)."</span>)"; ?>
Wrap the number so you can select is easily:
<?php echo 'Today (<span id="number">'.mysql_num_rows($query).'</span>)'; ?>
Then when a delete button is clicked:
// Get the number element once
var num = $('#number');
// Set an onclick event on your button
$('.delete').click(function(){
// Find the closest table row and remove it
$(this).closest( 'tr' ).remove();
// num.text() will get the text inside the number element
// parseInt is used to convert it from string to int
// subtract 1 to update the number
var newNumber = parseInt( num.text(), 10 ) - 1;
// And set the new number text
num.text( newNumber );
// Stop the default browser action - might cause the page to reload or to scroll
return false;
});
try it at: http://jsfiddle.net/xMZgv/7/
Today(<span id="counter">3</span>)
<table>
<tr><td>hello</td><td>delete</td></tr>
<tr><td>world</td><td>delete</td></tr>
<tr><td>hi</td><td>delete</td></tr>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.js"></script>
<script>
$(function() {
$('table tr').find('td:last').click(function() {
$(this).parent().remove();
$('#counter').html($('#counter').html() - 1)
})
})
</script>
Output your counter to a JavaScript var and use it in your loop and Today() function call. I'm assuming you're trying to output a client side function call from the server?
<?php echo "var count=".mysql_num_rows($query).";Today(count);" ?>
In your delete handler decrement count and call Today(count) again.
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;
});