Reputation: 13
I have a problem with my wp site... I have a post-type called "sezione". For each new post I create, a row is automatically added in a specific page. Each row has three input fields: in the first one I have to write number of males, in the second the number of females, while the third one is a readonly field with an automatic sum. I'm using a while loop like this:
<?php
query_posts( array(
'post_type' => 'sezione',
'orderby' => 'meta_value_num',
'meta_key' => 'n-sez',
'order' => 'ASC'
) );
if( have_posts() ) : while( have_posts() ) : the_post();
?>
<?php global $post; ?>
<?php
$nsez = get_post_meta($post->ID, 'n-sez', true);
?>
<div class="row-100perc-bord">
Sezione <?php echo $nsez; ?>
<div class="affl-box">
<input type="text" name="uomini<?php echo $nsez; ?>" id="uomini" class="field-50-u" value="<?php if ( isset ( $aff1t_stored_meta['uomini' . $nsez] ) ) echo $aff1t_stored_meta['uomini' . $nsez][0]; ?>" onblur="recalculateSummf();" />
<input type="text" name="donne<?php echo $nsez; ?>" id="donne" class="field-50-d" value="<?php if ( isset ( $aff1t_stored_meta['donne' . $nsez] ) ) echo $aff1t_stored_meta['donne' . $nsez][0]; ?>" onblur="recalculateSummf();" />
<input readonly type="text" name="totmf<?php echo $nsez; ?>" id="totmf" class="field-50-mf" value="<?php if ( isset ( $aff1t_stored_meta['totmf' . $nsez] ) ) echo $aff1t_stored_meta['totmf' . $nsez][0]; ?>" />
The loop works correctly. What I'm trying to do is to make the third field in each row display the sum of the values of the other two. I'm using this function:
function recalculateSummf()
{
var num1 = parseInt(document.getElementById("uomini").value);
var num2 = parseInt(document.getElementById("donne").value);
document.getElementById("totmf").value = num1 + num2;
}
But it works just in the first row. How can make this script works in all rows? May anybody help me in solving this issue? Thanks a lot!
Upvotes: 0
Views: 82
Reputation: 11040
Main issue: you should give an ID only once to any element on any page, ever.
If I understand you correctly, your HTML will look something like this.
<div class="row-100perc-bord">Sezione X
<div class="affl-box">
<input type="text" name="uominiX" id="uomini" class="field-50-u"
value="" onblur="recalculateSummf();" />
<input type="text" name="donneX" id="donne" class="field-50-d"
value="" onblur="recalculateSummf();" />
<input readonly type="text" name="totmfX" id="totmf" class="field-50-mf"
value="" />
</div>
</div>
<!-- ... more of the above, but with Sezione Y, Z, ... -->
Now, all of those have ID uomini
, donne
and totmf
. Using getElementById
to find them will always return the first ones.
Easy fix: add $nsez
to the IDs and use that. You will have to add $nsez
as an argument to your call of recalculateSummf
in the onblur
if you want to do this.
function recalculateSummf(sezione) {
var m = parseInt(document.getElementById('uomini' + sezione).value),
f = parseInt(document.getElementById('donne' + sezione).value);
document.getElementById('totmf' + sezione).value = m + f;
}
for (let sezione of ['X', 'Y', 'Z']) {
recalculateSummf(sezione);
}
<div class="row-100perc-bord">Sezione X
<div class="affl-box">
<input type="text" name="uominiX" class="field-50-u" id="uominiX"
value="10" onblur="recalculateSummf('X');" />
<input type="text" name="donneX" class="field-50-d" id="donneX"
value="42" onblur="recalculateSummf('X');" />
<input readonly type="text" name="totmfX" class="field-50-mf" id="totmfX" />
</div>
</div>
<div class="row-100perc-bord">Sezione Y
<div class="affl-box">
<input type="text" name="uominiY" class="field-50-u" id="uominiY"
value="16" onblur="recalculateSummf('Y');" />
<input type="text" name="donneY" class="field-50-d" id="donneY"
value="64" onblur="recalculateSummf('Y');" />
<input readonly type="text" name="totmfY" class="field-50-mf" id="totmfY" />
</div>
</div>
<div class="row-100perc-bord">Sezione Z
<div class="affl-box">
<input type="text" name="uominiZ" class="field-50-u" id="uominiZ"
value="1" onblur="recalculateSummf('Z');" />
<input type="text" name="donneZ" class="field-50-d" id="donneZ"
value="9" onblur="recalculateSummf('Z');" />
<input readonly type="text" name="totmfZ" class="field-50-mf" id="totmfZ" />
</div>
</div>
Alternative, that will update all sums on the page, is the following.
Loop over all .row-100perc-bord
containers and fix within that container.
function recalculateSummf() {
var containers = document.querySelectorAll('.row-100perc-bord');
for (let container of containers) {
let m = parseInt(container.querySelector('.field-50-u').value),
f = parseInt(container.querySelector('.field-50-d').value);
container.querySelector('.field-50-mf').value = m + f;
}
}
recalculateSummf();
<div class="row-100perc-bord">Sezione X
<div class="affl-box">
<input type="text" name="uominiX" class="field-50-u"
value="10" onblur="recalculateSummf();" />
<input type="text" name="donneX" class="field-50-d"
value="42" onblur="recalculateSummf();" />
<input readonly type="text" name="totmfX" class="field-50-mf" />
</div>
</div>
<div class="row-100perc-bord">Sezione Y
<div class="affl-box">
<input type="text" name="uominiY" class="field-50-u"
value="16" onblur="recalculateSummf();" />
<input type="text" name="donneY" class="field-50-d"
value="64" onblur="recalculateSummf();" />
<input readonly type="text" name="totmfY" class="field-50-mf" />
</div>
</div>
<div class="row-100perc-bord">Sezione Z
<div class="affl-box">
<input type="text" name="uominiZ" class="field-50-u"
value="1" onblur="recalculateSummf();" />
<input type="text" name="donneZ" class="field-50-d"
value="9" onblur="recalculateSummf();" />
<input readonly type="text" name="totmfZ" class="field-50-mf" />
</div>
</div>
If you add a this
argument to your recalculateSummf()
calls, you receive a reference to the input element that was blurred in your function. You can use this to update only the inputs that were changed.
function recalculateSummf(input) {
var container = input.parentNode,
m = parseInt(container.querySelector('.field-50-u').value),
f = parseInt(container.querySelector('.field-50-d').value);
container.querySelector('.field-50-mf').value = m + f;
}
var inputs = document.querySelectorAll('.field-50-u');
for (let input of inputs) {
recalculateSummf(input);
}
<div class="row-100perc-bord">Sezione X
<div class="affl-box">
<input type="text" name="uominiX" class="field-50-u"
value="10" onblur="recalculateSummf(this);" />
<input type="text" name="donneX" class="field-50-d"
value="42" onblur="recalculateSummf(this);" />
<input readonly type="text" name="totmfX" class="field-50-mf" />
</div>
</div>
<div class="row-100perc-bord">Sezione Y
<div class="affl-box">
<input type="text" name="uominiY" class="field-50-u"
value="16" onblur="recalculateSummf(this);" />
<input type="text" name="donneY" class="field-50-d"
value="64" onblur="recalculateSummf(this);" />
<input readonly type="text" name="totmfY" class="field-50-mf" />
</div>
</div>
<div class="row-100perc-bord">Sezione Z
<div class="affl-box">
<input type="text" name="uominiZ" class="field-50-u"
value="1" onblur="recalculateSummf(this);" />
<input type="text" name="donneZ" class="field-50-d"
value="9" onblur="recalculateSummf(this);" />
<input readonly type="text" name="totmfZ" class="field-50-mf" />
</div>
</div>
When you attach your event handlers programmatically, your function will receive an event
argument by default, that carries the target of the event, the input element that was blurred, with it. You can use this if you want, so you don't need to add an onblur
in your HTML at all.
function recalculateSummf(event) {
var input = event.target,
container = input.parentNode;
update(container);
}
function update(container) {
var m = parseInt(container.querySelector('.field-50-u').value),
f = parseInt(container.querySelector('.field-50-d').value);
container.querySelector('.field-50-mf').value = m + f;
}
// attach event handlers
var inputs = document.querySelectorAll('.field-50-u, .field-50-d');
for (let input of inputs) {
input.addEventListener('blur', recalculateSummf);
}
// update values initially
var containers = document.querySelectorAll('.row-100perc-bord');
for (let container of containers) {
update(container);
}
<div class="row-100perc-bord">Sezione X
<div class="affl-box">
<input type="text" name="uominiX" class="field-50-u"
value="10" />
<input type="text" name="donneX" class="field-50-d"
value="42" />
<input readonly type="text" name="totmfX" class="field-50-mf" />
</div>
</div>
<div class="row-100perc-bord">Sezione Y
<div class="affl-box">
<input type="text" name="uominiY" class="field-50-u"
value="16" />
<input type="text" name="donneY" class="field-50-d"
value="64" />
<input readonly type="text" name="totmfY" class="field-50-mf" />
</div>
</div>
<div class="row-100perc-bord">Sezione Z
<div class="affl-box">
<input type="text" name="uominiZ" class="field-50-u"
value="1" />
<input type="text" name="donneZ" class="field-50-d"
value="9" />
<input readonly type="text" name="totmfZ" class="field-50-mf" />
</div>
</div>
Upvotes: 1