PDA

View Full Version : adding in javascript...



JLAudioFan
01-11-2006, 08:23 PM
I have a simple task i'm trying to complete, and javascript is making me want to put my head through my monitor... here's the code:



<script language="javascript">
function doRetail(){
var a=document.form1.WholePrice.value * .4;
a+=document.form1.WholePrice.value;
document.form1.RetailPrice.value = a;
}
</script>


I have 2 form fields.
One is WholePrice (text box, where you'd put a wholesale price for a product)
other one is RetailPrice ( i want to mark up the WholePrice by 40 % and set this field equal to that value)

The problem is, javascript sees my variables as strings and not integers (so if i put 100 in wholesale, i end up with 40100 instead of 140)

Help is GREATLY appreciated. PHP is more my language, javascript is just such a pain ;)
Then again, it's been a few years since i've done any web design. Prolly a simple mistake.

jscheuer1
01-11-2006, 10:14 PM
You need to assure that you are working with a number, not a string. Sometimes simply doing arithmatic operations on a string that could be a number is enough:


<script language="javascript">
function doRetail(){
var a=document.form1.WholePrice.value * .4;
a+=(document.form1.WholePrice.value * 1);
document.form1.RetailPrice.value = a;
}
</script>

Otherwise, Math.abs may serve:


<script language="javascript">
function doRetail(){
var a=document.form1.WholePrice.value * .4;
a+=Math.abs(document.form1.WholePrice.value);
document.form1.RetailPrice.value = a;
}
</script>

This still might not be enough, then you may need:


<script language="javascript">
function doRetail(){
var a=document.form1.WholePrice.value * .4;
a=Math.abs(document.form1.WholePrice.value)+Math.abs(a);
document.form1.RetailPrice.value = a;
}
</script>

JLAudioFan
01-11-2006, 10:58 PM
Great, thanks a ton John!

I didn't know about the Math.abs function, looks like that's what I needed.

Once again, thanks. That was driving me crazy!

JLAudioFan
01-12-2006, 06:50 PM
Question for whoever would like to answer:

Let's say I had multiple form items on this page, named WholePrice1, WholePrice2, etc (generated with PHP). Could I change my function to this??



<script language="javascript">
function doRetail(x){
var a=document.form1.WholePrice[x].value * .4;
a=Math.abs(document.form1.WholePrice[x].value)+Math.abs(a);
document.form1.RetailPrice[x].value = a;
}
</script>


I've tried it, and it doesn't work. Does Javascript have a different method of dealing with arrays? I figured if i passed "x" thru with the function, I could use it.

jscheuer1
01-12-2006, 10:53 PM
With code like that, it would depend upon what your HTML markup looks like and upon what browser you are using. Cross browser code and markup can be written to do that. Javascript does do arrays like that but, will not recognize arrays unless they are constructed following the rules of both javascript and (more importantly, in this case) the HTML parsing rules of the browser (if applicable, as they likely are here). To save time and guesswork on my part, could you supply the HTML markup you are trying this with?

mwinter
01-13-2006, 01:34 AM
<script language="javascript">The language attribute has been deprecated in favour of the type attribute for a long time now:



<script type="text/javascript">



function doRetail(){
var a=document.form1.WholePrice.value * .4;
a+=document.form1.WholePrice.value;If this price is entered by a user, the first thing you should consider is validating that input:



function doRetail() {
var controls = document.forms.form1.elements,
wholesale = controls.WholePrice.value;

if(!/^\d+$/.test(wholesale) && ((wholesale = +wholesale) > 0)) {
alert('The wholesale price must be a valid number.');
return;
}
controls.RetailPrice.value = wholesale * 1.4;
}
You mention integers, so the regular expression above will only permit whole numbers. If you really intend any real, floating-point number, then the expression can be changed to



/^(0|[1-9]\d*)(\.\d+)?$/
If validation isn't an issue, then you can avoid the entire issue by performing a simple multiplication:



function doRetail() {
var controls = document.forms.form1.elements;

controls.RetailPrice.value = controls.WholePrice.value * 1.4;
}



Let's say I had multiple form items on this page, named WholePrice1, WholePrice2, etc (generated with PHP).If you mean that the document will contain controls with names like 'WholePrice1' and 'WholePrice2', then the function can be parameterised but not in the way you suggest.


document.form1.WholePrice[x]The document won't actually have an array of 'WholePrice' controls. There will be a discrete set of uniquely named controls. You'd have to access them - taking the second example above - like so:



function doRetail(index) {
var controls = document.forms.form1.elements;

controls['RetailPrice' + index].value = controls['WholePrice' + index].value * 1.4;
}
That is, you construct the property names at run-time.

Hope that helps,
Mike

JLAudioFan
01-17-2006, 12:07 AM
Wow, that's alot of info to absorb... Here's the HTML markup that i'm using.



<table border="0" cellspacing="0" cellpadding="5">
<tr>
<td class="genericText"><div align="center">Item To add </div></td>
<td class="genericText"><div align="center">Case Cost </div></td>
<td class="genericText"><div align="center">CaseCount</div></td>
<td class="genericText"><div align="center">Wholesale Price </div></td>
<td class="genericText"><div align="center">Retail Price </div></td>
<td class="genericText"><div align="center">Amt Rec'd </div></td>
<td class="genericText"><div align="center">asdfasdf</div></td>
<td class="genericText"><div align="center">asdfasdf</div></td>
</tr>
<? for($x = 0;$x < $y;$x++){ ?>
<tr>
<td class="genericText"><div align="center">
<select name="invselect[<?=$x?>]" class="genericText">
<option value="none" <? if(!$_POST['invselect'][$x]){?>selected<? } ?>>Select --></option>
<?php
do {
?>
<option value="<?php echo $row_inventory['idInventory']?>"<? if($_POST['invselect'][$x] == $row_inventory['idInventory']){ print " selected"; } ?>><?php echo $row_inventory['Description']?></option>
<?php
} while ($row_inventory = mysql_fetch_assoc($inventory));
$rows = mysql_num_rows($inventory);
if($rows > 0) {
mysql_data_seek($inventory, 0);
$row_inventory = mysql_fetch_assoc($inventory);
}
?>
</select>
</div></td>
<td class="genericText"><div align="center">
<input name="CaseCost[<?=$x; ?>]" type="text" class="genericText" id="CaseCost" size="5" value="<?=$_POST['CaseCost'][$x]?>">
</div></td>
<td class="genericText"><div align="center">
<input name="CaseCount[<?=$x; ?>]" type="text" class="genericText" id="CaseCount" value="<?=$_POST['CaseCount'][$x]?>" size="5">
</div></td>
<td class="genericText"><div align="center">
<input name="WholePrice[<?=$x; ?>]" type="text" onBlur="doRetail(<?=$x?>);" class="genericText" value="<?=$_POST['WholePrice'][$x]?>" size="5" />
</div></td>
<td class="genericText"><div align="center">
<input name="RetailPrice[<?=$x; ?>]" type="text" class="genericText" value="<?=$_POST['RetailPrice'][$x]?>"size="5" />
</div></td>
<td class="genericText"><div align="center">
<input name="addToInv[<?= $x; ?>]" type="text" class="genericText" id="addToInv" value="<?=$_POST['addToInv'][$x]?>" size="5">
</div></td>
<td class="genericText"><div align="center"></div></td>
<td class="genericText"><div align="center"></div></td>
</tr>
<? } ?>
</table>


The form fields have names like WholePrice[x] where x is dynamic (I have a button that when clicked, it reloads the page, adding another set of fields that the user can input information)

I'm using FireFox (will be what this software is built for) so I don't need to work around any other browsers)

The data that i will need to manipulate would be a number like "1.79", so i only need 2 decimal places.

This is what I am trying to get to work, but I must say I'm kind of lost...



function doRetail() {
var controls = document.forms.form1.elements,
wholesale = controls.WholePrice.value;

if(!/^\d+$/.test(wholesale) && ((wholesale = +wholesale) > 0)) {
alert('The wholesale price must be a valid number.');
return;
}
controls['RetailPrice' + index].value = controls['WholePrice' + index].value * 1.4;
}


I don't know if i forgot to change something specific to my file, but this doesnt do anything (that I can see anyways).

Once again, I thank you for your help!

Jason

jscheuer1
01-17-2006, 05:50 AM
One problem with what you've posted is, there is no form whatsoever, let alone one named form1. In case that wasn't just an oversight on your part, to have a form in HTML requires more than just having form elements like 'input', etc. You must also layout the form using the form tag:

<form name="form1">
things like inputs and buttons go here
</form>

JLAudioFan
01-17-2006, 08:22 AM
There is a form named form1 in the file, I only posted the section I'm having problems with.

jscheuer1
01-17-2006, 07:49 PM
Well, I can't set up a test page without at least the markup referenced by the script. Better yet, give us the whole page or best, a link to it.

mwinter
01-17-2006, 10:58 PM
<table border="0" cellspacing="0" cellpadding="5">
&#160;&#160;<tr>
&#160;&#160;&#160;&#160;<td class="genericText"><div align="center">Item To add </div></td>You really should consider thinning that markup out. Rather than labelling everything in sight as 'genericText', and using div elements to centre text, just use a little CSS. Consider:



#order {
/* Define the properties of 'genericText' here. */
}
#order th,
#order td {
text-align: center;
}


<table id="order">
<thead>
<tr>
<th>Case Cost</th>
<th>Case Count</th>
<th>Wholesale Price</th>
<th>Retail Price</th>
<th>Amount Received</th>
</tr>
</thead>

<tbody>
<tr>
<td>
<select name="invselect[0]">
<option value="none">[Select]</option>
<option value="...">...</option>
</select>
</td>
<td>
<input name="CaseCost[0]" type="text" size="5" value="...">
</td>
<td>
<input name="CaseCount[0]" type="text" size="5" value="...">
</td>
<td>
<input name="WholePrice[0]" type="text" size="5" value="..." onchange="doRetail(0, this);">
</td>
<td>
<input name="RetailPrice[0]" type="text" size="5" value="...">
</td>
<td>
<input name="addToInv[0]" type="text" size="5" value="...">
</td>
</tbody>
</table>
Notice a few things. The id attributes have been removed from the form controls. For a start, the values must be unique within a document (yours weren't) and they aren't necessary, anyway. The table has been restructured and more semantic; column headers are actually marked up with the appropriate cell type. The call to doRetail has been altered, and uses a different event (this will be explained later).

A final note here, is that the CSS presented is rather simplistic. As I don't know what your 'genericText' is supposed to look like, I can't offer much more. However, the point is that many CSS properties are inherited, or can be applied in a much simpler way than adding class attributes to virtually every element.


The form fields have names like WholePrice[x] [...]Ah, well you didn't mention that before. It's not a problem, but the solution I posted previously would need to be modified slightly.


The data that i will need to manipulate would be a number like "1.79", so i only need 2 decimal places.You'd also have to use the other regular expression I posted as the current one would reject such a number (it's not an integer).

Back to the changes I suggested above, with regards to the client-side code. I'll start with the event type.

When validating and presenting a warning to the user, the blur event should not be used. Bugging the user constantly is not a good idea. The user should only be prompted when they actually change input and it's wrong, not if they just tabbed past a field that, by default (or in its current state), is invalid. If the user accidentally forgets a field before submitting, a listener on the submit event (or server-side) can catch that error, anyway). There's another reason, but it doesn't apply at the moment, so I'll skip it for now.

Now, to the call. The change was to add the this operator as an argument. In event listeners, the this operator refers to the element firing the event. This makes referencing the element, its value, and the containing form a little easier. The validation function you would want to use, at the moment, would look like:



function doRetail(index) {
var controls = document.forms.form1.elements,
wholesale = controls['WholePrice[' + index + ']'].value;

if(!/^(0|[1-9]\d*)(\.\d{1,2})?$/.test(wholesale) && ((wholesale = +wholesale) > 0)) {
alert('The wholesale price must be a valid number.');
return false;
}

controls['RetailPrice[' + index + ']'].value = wholesale * 1.4;
return true;
}
With the proposed changes, it can be simplified slightly to:



function doRetail(index, element) {
var wholesale = element.value;

if(!/^(0|[1-9]\d*)(\.\d{1,2})?$/.test(wholesale) && ((wholesale = +wholesale) > 0)) {
alert('The wholesale price must be a valid number.');
return false;
}

element.form.controls['RetailPrice[' + index + ']'].value = wholesale * 1.4;
return true;
}
Although the saving isn't tremendous, it's again a demonstration of principle as doing this sort of thing can make code significantly simpler and more reusable. If you made other code you might have follow a similar pattern, you could also now remove the name attribute from the form as nothing would need it.

Hope that helps,
Mike

JLAudioFan
01-20-2006, 12:21 AM
You really should consider thinning that markup out. Rather than labelling everything in sight as 'genericText', and using div elements to centre text, just use a little CSS.

Most of that ID stuff was dreamweaver's doing, not mine. I like using the div tags personally, but now that I think about it I can see how the ID attribs could mess up scripts.


When validating and presenting a warning to the user, the blur event should not be used. Bugging the user constantly is not a good idea. The user should only be prompted when they actually change input and it's wrong, not if they just tabbed past a field that, by default (or in its current state), is invalid. If the user accidentally forgets a field before submitting, a listener on the submit event (or server-side) can catch that error, anyway). There's another reason, but it doesn't apply at the moment, so I'll skip it for now.

I had this function on the onBlur() for a specific reason. They enter the wholesale price of something, and as soon as they're done entering it and tab or click out of the box, the retail price pops in there automatically (but can still be changed if needed). That was user requested. I really do dislike forms that constantly bother me though, so I agree with you there.


Although the saving isn't tremendous, it's again a demonstration of principle as doing this sort of thing can make code significantly simpler and more reusable. If you made other code you might have follow a similar pattern, you could also now remove the name attribute from the form as nothing would need it.

Hope that helps,
Mike

I'm sure it will help Mike. I've also pm'ed you a link to the page, and set you up with a user/pass. This software is still in developmental stages so there's lots of input controls and checks that are not in place (keep in mind if you decide to play around with it ;)). The page in question here is the add shipments page. Thanks again for all your help!

Jason

JLAudioFan
01-24-2006, 04:22 AM
Ok, this is really frustrating me. I seem to be making backwards progress.

I had the script calculating the retail price, no problems there. This is on a separate page, with only WholePrice and RetailPrice form fields... now I can't get it to work at all. I've tried these functions...


function doRetailSimple(){
var a=document.form1.WholePrice.value * 1.4;
a=Math.abs(a);
document.form1.RetailPrice.value = a;
}

function sum(objRef) {
var result = 0;
result =+ objRef.WholePrice.value - 0;
var retail = result * 1.4;
objRef.RetailPrice.value = retail;
}

function doIT(){
var a=document.form1.WholePrice.value - 0;
a=document.form1.WholePrice.value * 1.4;

document.form1.RetailPrice.value = a;
}

function calculate(what) {
answer=0;
answer += what.elements['WholePrice'].value - 0;
answer += what.elements['WholePrice'].value * 1.4;
what.RetailPrice.value = answer;
}

None of them work for me. I really don't know what to do. I only wish PHP could replace javascript.

Please help.