Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 22

Thread: Live Field Calculations

  1. #11
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    29,069
    Thanks
    44
    Thanked 3,216 Times in 3,178 Posts
    Blog Entries
    12

    Default

    BTW, if you want to (using the code I wrote) get the % based upon the total charged rather than as a % of the base price:

    Code:
    <script type="text/javascript">
    function tot(t){
    var f=t.form.elements, e=['oc','ww'];
    for (var i = 0; i < e.length; i++)
    if(!f[e[i]].value||isNaN(f[e[i]].value-0))
    return;
    var m=f.ww.value-0, b=f.oc.value-0;
    f.op.value=m-b;
    f.pp.value=Math.round(((m-b)/m)*100);
    }
    </script>
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  2. #12
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    29,069
    Thanks
    44
    Thanked 3,216 Times in 3,178 Posts
    Blog Entries
    12

    Default

    Here's my self initialization version:

    Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
    <head>
    <title></title>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
    <style type="text/css">
    .calc, .calc table {
    border-collapse:collapse;
    margin:0;
    }
    .calc th {
    font:bold 70% arial, sans-serif;
    padding:.5em 0;
    color:black;
    text-align:left;
    background-color:#c5c8b2;
    text-indent:.5em;
    }
    .calc td {
    background-color:#eceddf;
    font:75% arial, sans-serif;
    padding:.5em .5ex;
    color:#8a8b7e;
    }
    .calc input {
    width:7em;
    }
    </style>
    <script type="text/javascript">
    function tot(){
    var f=this.form.elements, e=['oc','ww'];
    for (var i = 0; i < e.length; i++)
    if(!f[e[i]].value||isNaN(f[e[i]].value-0))
    return;
    var m=f.ww.value-0, b=f.oc.value-0;
    f.op.value=m-b;
    f.pp.value=Math.round(((m-b)/b)*100);
    }
    tot.init=function(){
    var f=document.forms, e='elements', ev=['keyup','mouseover','mouseout'],
    a=function(el, e){el[e]=function(){tot.apply(el);};}, r=function(){return false;};
    for (var i = 0; i < f.length; i++)
    if(f[i].className=='calc'){
    f[i].onsubmit=r;
    for (var j = 0; j < f[i][e].length; j++)
    if(/^(oc)|(ww)$/.test(f[i][e][j].name))
    for (var z in ev)
    a(f[i][e][j],'on'+ev[z]);
    else if(/^(op)|(pp)$/.test(f[i][e][j].name))
    f[i][e][j].setAttribute('readonly', 1, 0);
    }
    };
    </script>
    </head>
    <body>
    <form class="calc" action="javascript:void(0);">
    <table>
    <tr>
    <th>Our Cost</th><th>What We Charge</th><th>Our Profit</th><th>% Profit</th>
    </tr>
    <tr>
    <td><input type="text" name="oc"></td>
    <td><input type="text" name="ww"></td>
    <td><input type="text" name="op"></td>
    <td>% <input type="text" name="pp"></td>
    </tr>
    </table>
    </form>
    <form class="calc" action="javascript:void(0);">
    <table>
    <tr>
    <th>Our Cost</th><th>What We Charge</th><th>Our Profit</th><th>% Profit</th>
    </tr>
    <tr>
    <td><input type="text" name="oc"></td>
    <td><input type="text" name="ww"></td>
    <td><input type="text" name="op"></td>
    <td>% <input type="text" name="pp"></td>
    </tr>
    </table>
    </form>
    <script type="text/javascript">
    tot.init();
    </script>
    </body>
    </html>
    Note: Once again, if you want the % to be of the total price charged change the last b to an m.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  3. #13
    Join Date
    Nov 2007
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    I have one last fish to fry before I go modular.

    This one is truly baffling

    Code:
    var vdiscount = discount.value.trim();
    var ndiscount = 1 - ((vdiscount*1)/100);
    
    subtotal.value = (subtotal.value * ndiscount).toFixed(2);
    I get some weird percentages thanks to Line 2. Apparently js doesn't like it when I subtract from 1.

    As an example it tells me that 10% off on 100 = 89.1

    If I get rid of the 1 - part, it all works flawlessly.

  4. #14
    Join Date
    Mar 2005
    Location
    SE PA USA
    Posts
    29,069
    Thanks
    44
    Thanked 3,216 Times in 3,178 Posts
    Blog Entries
    12

    Default

    Both of my versions are already modular.
    - John
    ________________________

    Show Additional Thanks: International Rescue Committee - Donate or: The Ocean Conservancy - Donate or: PayPal - Donate

  5. #15
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    I guess it is due to a rounding error? (If its not simply a logic error on your part.) If so, then this might work
    Code:
    var ndiscount = (100 - vdiscount)/100;
    I just factored out the 1/100

    In any case, John's code is good. You might want to consider using his.
    Trinithis

  6. #16
    Join Date
    Nov 2007
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Thanks for the code John..I cant believe how small a footprint it has. Of course I cant understand a word of it :P.

    Trinithis's solution was more verbose, but I managed to twist it to suit my needs. Its actually pretty flexible, I can deduce fields in a variety of ways and even got some advanced discount math happening.

    The only bad part is that I totally butchered the code :P

    Seriously if any of you have suggestions on how I can suck less, I'm all ears.
    Last edited by pimpmaster; 11-08-2007 at 12:08 AM.

  7. #17
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    Quote Originally Posted by pimpmaster View Post
    Seriously if any of you have suggestions on how I can suck less, I'm all ears.
    Perhaps an explanation of John's code would help you learn a little

    Expanded, his JS looks like:
    Code:
    function tot() {
    	var f = this.form.elements;
    	var e = ['oc','ww'];
    	for(var i=0; i<e.length; i++)
    		if(!f[e[i]].value || isNaN(f[e[i]].value-0)) return;
    	var m = f.ww.value-0;
    	var b = f.oc.value-0;
    	f.op.value = m-b;
    	f.pp.value = Math.round(((m-b)/b)*100);
    }
    
    tot.init = function() {
    	var f = document.forms;
    	var e = 'elements';
    	var ev = ['keyup', 'mouseover', 'mouseout'];
    	var a = function(el, e) {
    		el[e] = function() {
    			tot.apply(el);
    		};
    	};
    	var r = function() {
    		return false;
    	};
    	for(var i=0; i<f.length; i++)
    	if(f[i].className=='calc') {
    		f[i].onsubmit = r;
    		for(var j=0; j<f[i][e].length; j++)
    		if(/^(oc)|(ww)$/.test(f[i][e][j].name))
    			for (var z in ev)
    				a(f[i][e][j], 'on'+ev[z]);
    		else if(/^(op)|(pp)$/.test(f[i][e][j].name))
    			f[i][e][j].setAttribute('readonly', 1, 0);
    	}
    };
    And my explanation of it:

    I think the first function, tot should be relatively easy to understand. It's much like the anonymous function I defined within the calls of my addEvent. All you need to know is that this refers to the form element that called it. More on that later.

    tot.init you can think of as an init function with a namespace, tot. The code
    Code:
    e = 'elements'
    is created to be used as shorthand for
    Code:
    f[i][e] == f[i].elements
    In case you were wondering, you can access any property of an object using dot notation or array notation:
    Code:
    obj.prop == obj["prop"]  //same thing!
    Looking at the function a, all it does is take two arguments, an element and an event. Then it says el[e], which might describe something as follows:
    Code:
    //el.onevent = function(e) {...};
    myElement.onclick = function(e) {...};
    div1.onkeyup = function(e) {...};
    Adding events this way is much like using addEventListener or attachEvent. The only difference is that you can't directly add two events of the same type to an element this way. (And addEventListener allows you to specify whether or not an event bubbles or not.)

    In any case, the function being assigned to do the work of that event is tot.apply(el). This just means call the tot function, and wherever you see the keyword this, give it the value el.

    The function r defined in here is just to make the form do nothing when you submit it when you later assign
    Code:
    f[i].onsubmit = r
    The following loop looks at every form and sees if it has the class "calc". In other words, it looks for the appropriate forms to do its magic on. If a match is found, it then looks at all its elements (all the form-related tags (perhaps all its other child tags as well?) within it ... like the input tag) and tests to see if the name of the tag is "oc" or "ww". Thats what
    Code:
    if(/^(oc)|(ww)$/.test(f[i][e][j].name))
    does. /^(oc)|(ww)$/ is a regex (regular expression) that sees if the characters "oc" or "ww" start and end the string it is tested against. In this case, that string would be the field name.

    Should the regex test pass, then you know that the element (the tag) you are dealing with is either a "Our Cost" or a "What We Charge" input field. So we use a for-in loop to extract each element (not the same as an html element) in the array ev one at a time, which contains the values "keyup", "mouseover", and "mouseout". Within the loop, the extracted value is put into the variable z, and we call the function a with some paramaters, which, in all adds the events to the (html) element at hand.

    Should the regex fail, we look and see if the element name is "op" or "pp". If it is, then make it read-only.
    Last edited by Trinithis; 11-07-2007 at 12:38 AM.
    Trinithis

  8. #18
    Join Date
    Nov 2007
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Thanks for taking the time to explain.. you make it sound so easy!

    I suppose my problem with examples like these is that I tend to prefer explicit over clever code. I program in Ruby so maybe that has something to do with it.

    I'm also trying to keep my JS as unobtrusive as possible, which is why your example (though not was neat and compact) is almost preferable since it works off DOM hooks. (Yes I am an HTML snob )

    I'm going to read your post again a few times and let it sink in some more. Hopefully I will be able to extend John's code like I did with yours (minus the complete butchery)

    Thanks to both of you for your sage-like patience

  9. #19
    Join Date
    Nov 2007
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Argh.. I been trying to hook this up so that I can also type inside the percentage field and have that deduct the charge field (will do profit too once I figure this out) So far I havent been successful. I am guessing that perhaps I need to write a separate function for this??

    Here is my tweak (pastied for extra pimp factor):

    http://pastie.textmate.org/115275

    Another issue I'm having is the fact that I need these multiple rows of inputs to live in one form. Is this possible?
    Last edited by pimpmaster; 11-08-2007 at 12:01 AM.

  10. #20
    Join Date
    Nov 2007
    Posts
    11
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    LOL.. sometimes coding late at night is not the best idea. After racking my brain for a good hour, I realized that finding a charge by percent is a mathematical impossibility (unless I am calculating it off the cost, which is not what I want) Doh...

    At this point I only have one obstacle left and thats the ability to have an unlimited number of these calculation rows inside a form, while not losing the ability to have multiple forms on a page.

    Any ideas?

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •