Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    New to the CF scene
    Join Date
    Dec 2009
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Forms - Keeping a Running Total

    Beginner here, so please bear with me... Essentially, I'm trying to put together a survey which keeps a running total at the bottom of the page that is updated each time the user makes a choice. So, something like this:

    Checkbox A - $5.00
    Checkbox B - $10.00
    Checkbox C - $20.000
    Total _____
    (Where Total is a textbox.)

    Originally, I thought this would be easy -- I could just include the onClick attribute in the input tags and call a function each time a checkbox is selected. The problem is that the survey software I'm using doesn't seem to allow me to alter the input tags. Basically, I can create the survey using their customized software and it generates the form, input tags, etc. I can then add customized html/javascript before and after each question. All the code I add appears within the same form.

    So, is there an easy way to solve this problem without altering the input tags?

  • #2
    Senior Coder jmrker's Avatar
    Join Date
    Aug 2006
    Location
    FL
    Posts
    3,075
    Thanks
    38
    Thanked 498 Times in 492 Posts
    Hard to say without a simple example.

    Create a form with 3 or so survey questions.
    Perhaps we'll be able to see where to add the extra code.

  • #3
    New to the CF scene
    Join Date
    Dec 2009
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Thanks for your response

    I tried to specify where it was possible to add code. Sorry if the script is hard to read.

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="en-us" ><head>
    <title>Test 2</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta name="robots" content="NOINDEX,NOFOLLOW" />
    <style type="text/css" media="screen">
    @import url( X );
    .sg_FrameSet {border: none; padding:0; margin:0;}


    </style>
    <script src="X" type="text/javascript" ></script>
    </head>
    <body class="sg_Body sg_PageNum_1 sg_PageIdent_1" onload="sg_question_renumber();" >
    <form action="preview_survey_bottom.php" method="post" enctype="multipart/form-data" class="sg_Survey_Form" id="sg_FormFor218685" >
    <div id="sg_wrapper">
    <div id="sg_header">

    <div id="sg_header_hook_1"></div>
    <img src="X" class="sg_headerImage" alt="Logo"/>
    <h1 class="sg_Title"><span>Test 2</span></h1>
    <div class="sg_page_title" >Page One</div>
    <div id="sg_header_hook_2"></div>
    </div>

    <div id="sg_content">
    <div id="sg_content_hook_1"></div>

    <!-- QUESTIONS INSERTED HERE -->
    <div class="sg_QuestionSet"><!-- QS Start -->

    <div class="sg_Question sg_CheckboxWrapper" id="sg_dhtml_q2" >
    <input type="hidden" id="hidden_2" name="hidden_2" value="false" />


    <div class="sg_QuestionTitle"><script type="text/javascript" >var sg_first_number = 1;</script>
    <span class="qNumber" id="qNumber_2" >1. </span>Choose your option <br />
    I can add code here</div>

    <div class="sg_ControlSet" >
    <div class="sg_Checkbox_Options" >
    <table class="sg_Table" cellspacing="0" >
    <tr class="noFlicker" id="option_Q_2_O0" ><td class="sg_TD1" ><input class="sg_Checkbox" type="checkbox" name="Q_2_O0" id="Q_2_O0" title="A - $5.00" value="A - $5.00" /></td><td class="sg_TD2" ><label for="Q_2_O0" >A - $5.00</label></td></tr>
    <tr class="noFlicker" id="option_Q_2_O1" ><td class="sg_TD1" ><input class="sg_Checkbox" type="checkbox" name="Q_2_O1" id="Q_2_O1" title="B - $10.00" value="B - $10.00" /></td><td class="sg_TD2" ><label for="Q_2_O1" >B - $10.00</label></td></tr>
    <tr class="noFlicker" id="option_Q_2_O2" ><td class="sg_TD1" ><input class="sg_Checkbox" type="checkbox" name="Q_2_O2" id="Q_2_O2" title="C- $20.00" value="C- $20.00" /></td><td class="sg_TD2" ><label for="Q_2_O2" >C- $20.00</label></td></tr>
    </table></div></div>

    <div class="sg_Question_Footer"></div>

    </div>

    <div class="sg_Question sg_InstructionsWrapper" id="sg_dhtml_q3" >
    <input type="hidden" id="hidden_3" name="hidden_3" value="false" />

    <div class="sg_QuestionTitle"></div>
    <div class="sg_ControlSet" ><div class="sg_Instructions" >I can add code here</div></div>
    <div class="sg_Question_Footer"></div>

    </div>

    <!-- QS End --></div><script type="text/javascript" >
    //<![CDATA[
    function sg$(id){return(document.getElementById(id));}
    if(typeof $ != 'function'){
    function $(id){return(sg$(id));}
    }
    function attachEventListener(target, eventType, functionRef, capture){if(typeof target.addEventListener != "undefined"){target.addEventListener(eventType,functionRef,capture);} else if(typeof target.attachEvent != "undefined"){target.attachEvent("on" + eventType,functionRef);};}
    function sgjsGetEventTarget(event){var targetElement = null;if(typeof event.target != "undefined"){targetElement = event.target;} else {targetElement = event.srcElement};while(targetElement.nodeType == 3 && targetElement.parentNode != null){targetElement = targetElement.parentNode;};return targetElement;}
    if(typeof getEventTarget != 'function'){getEventTarget = sgjsGetEventTarget;}

    function sgjsAddError(elementid,id,message)
    {
    sgjsRemoveError(elementid,id);
    eval("if( typeof errors_" + elementid + " == 'undefined')errors_" + elementid + " = Array();");
    var error = Array();
    error[0] = id;
    error[1] = message;
    eval("errors_" + elementid + ".push(error);");
    if( typeof total_errors == 'undefined')total_errors = 0;
    total_errors++;
    }


    //]]>
    </script>
    <div class="clear"></div>


    <div id="sg_content_hook_2"></div>
    </div>

    <div id="sg_footer">
    <div id="sg_footer_hook_1">
    <div class="sg_Button_Group">

    <input type="submit" class="sg_Submit" id="sg_SubmitButton" name="sGizmoSubmitButton" onclick="if(typeof total_errors != 'undefined' &amp;&amp; total_errors &gt;0){alert('You have errors on this page, please correct them before pressing this button.');return(false);};document.getElementById('sGizmoAJAXSubmitButtonUsed').value='sGizmoSubmitB utton';return(true);" value="Finished? Submit your Survey" />

    </div>
    <!-- PROGRESS BAR --><div class="progressBar"><div id="sg_ProgressBar" style="background-repeat: no-repeat; background-position: -100px center;width:200px;">50%</div></div>
    </div>
    <div id="sg_footer_hook_2"></div>
    </div>
    </div>
    <input type="hidden" name="sGizmoCurrent_Fields" id="sGizmoCurrent_Fields" value="Q_2_O0,Q_2_O1,Q_2_O2,Q_3" /><input type="hidden" name="sGizmoCurrentPageNum" id="sGizmoCurrentPageNum" value="1" /><input type="hidden" name="sGizmoCurrentPageIndex" id="sGizmoCurrentPageIndex" value="1" /><input type="hidden" name="sGizmoCurrentSection" value="1" /><input type="hidden" name="sGizmoAJAXSubmitButtonUsed" id="sGizmoAJAXSubmitButtonUsed" value="" /><input type="hidden" name="sGizmoNextPageNum" value="2" /><input type="hidden" name="sgTimeStamp" value="1260731978" /></form>
    <div style="color:black;font:normal 10px/12px arial;margin-top:20px;" class="sg_PoweredBy" ><a href="X" target="_blank" ><img src="/images/surveys/underTheHood.gif" alt="Online Survey Software" border="0" /></a><br /><a href="X" target="_blank" style="color:black;font-size:9px;white-space:nowrap">Online Surveys</a> powered by X</div>
    </body></html>

  • #4
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,171
    Thanks
    75
    Thanked 4,338 Times in 4,304 Posts
    I'd bet that the easiest way to do this would *NOT* be to attach onclick events to the checkboxes.

    Instead, just run a timer (setInterval) that goes out every 100 milliseconds or so and tests the state of all checkboxes and updates the total.

    Code:
    <script type="text/javascript">
    function updateTotal( )
    {
        var cbs = document.getElementsByTagName("input");
        var total = 0;
        for ( c = 0; c < cbs.length; ++c )
        {
            var cb = cbs[c];
            if ( cb.type != null && cb.type == "checkbox" && cb.checked )
            {
                total += parseFloat( cb.value.replace(/[^\d\.]/g,"") );
            }
        }
        document.getElementById("id_of_the_total_field").value = "$" + total.toFixed(2);
    }
    setInterval( "updateTotal()", 100 );
    </script>
    Probably be nice to not start the interval ticking until page load, but you could probably finesse that, too, by just doing:
    Code:
    function updateTotal( )
    {
        var cbs = document.getElementsByTagName("input");
        if ( cbs == null ) return; // don't do anything if you can't find the collection
        ...
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • Users who have thanked Old Pedant for this post:

    Fiona (12-13-2009)

  • #5
    Senior Coder jmrker's Avatar
    Join Date
    Aug 2006
    Location
    FL
    Posts
    3,075
    Thanks
    38
    Thanked 498 Times in 492 Posts

    Lightbulb Try this ...

    'Old Pedant' may be right, but this is my attempt at the problem.
    His function to convert the input.value to a number is probably better than mine.

    Since you did not include the CSS it may look different.

    Code:
    <html>
    <head>
    <title>Survey Sums</title>
    <script type="text/javascript">
    // From: http://www.codingforums.com/showthread.php?t=184435
    
    function getAmount(IDS) {
    	var tmp = document.getElementById(IDS).value;
    	var str = '';
    	for (var i=0; i<tmp.length; i++) {
    		if ('0123456789.'.indexOf(tmp[i]) != -1) { str += tmp[i]; }
    	}  // alert(str);  // for testing purposes
    	return parseFloat(str);
    }
    function Summate() {
      inputTags = document.getElementsByTagName('input');
      var total = 0;
      for (var i=0; i<inputTags.length; i++) {
    //	if (inputTags[i].checked) { total++; }  // for testing purposes
    	if (inputTags[i].checked) { total += getAmount(inputTags[i].id); }
      }
      document.getElementById('summation').innerHTML = total.toFixed(2);
    }
    
    // From: http://ejohn.org/blog/flexible-javascript-events/
    function addEvent( obj, type, fn ) {
      if ( obj.attachEvent ) {
        obj['e'+type+fn] = fn;
        obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
        obj.attachEvent( 'on'+type, obj[type+fn] );
      } else
        obj.addEventListener( type, fn, false );
    }
    
    function SetAction() {
      inputTags = document.getElementsByTagName('input');
      for (var i=0; i<inputTags.length; i++) {
    //	addEvent(document.getElementById(inputTags[i].id),'click',Summate); 
    	addEvent(document.getElementById(inputTags[i].id),'change',Summate);
    	 
    //    alert('inputTag: '+i+' :'+inputTags[i].value);  // for testing purposes
      }
    }
    
    window.onload = function() {
      SetAction();
    }
    </script>
    </head>
    <body>
    <form name="myform">
    <div class="sg_ControlSet" >
     <div class="sg_Checkbox_Options" >
      <table class="sg_Table" cellspacing="0" >
       <tr class="noFlicker" id="option_Q_2_O0" >
        <td class="sg_TD1" >
         <input class="sg_Checkbox" type="checkbox" name="Q_2_O0" id="Q_2_O0"
          title="A - $5.00" value="A - $5.00" />
        </td>
        <td class="sg_TD2" >
         <label for="Q_2_O0" >A - $5.00</label>
        </td>
       </tr>
       <tr class="noFlicker" id="option_Q_2_O1" >
        <td class="sg_TD1" >
         <input class="sg_Checkbox" type="checkbox" name="Q_2_O1" id="Q_2_O1"
          title="B - $10.00" value="B - $10.00" />
        </td>
        <td class="sg_TD2" >
         <label for="Q_2_O1" >B - $10.00</label>
        </td>
       </tr>
       <tr class="noFlicker" id="option_Q_2_O2" >
        <td class="sg_TD1" >
         <input class="sg_Checkbox" type="checkbox" name="Q_2_O2" id="Q_2_O2"
          title="C- $20.00" value="C- $20.00" />
        </td>
        <td class="sg_TD2" >
         <label for="Q_2_O2" >C- $20.00</label>
        </td>
       </tr>
      </table>
      <div id="summation">Summation: </div>
     </div>
    </div>
    </form>
    </body>
    </html>
    I'm not sure why you can change a portion of the HTML, but not the <input> tags (?)

    Probably needs some more work, but good luck.

  • Users who have thanked jmrker for this post:

    Fiona (12-13-2009)

  • #6
    New to the CF scene
    Join Date
    Dec 2009
    Posts
    3
    Thanks
    2
    Thanked 0 Times in 0 Posts

    Thank you!

    This works beautifully. Thank you both so much for your help!

  • #7
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,171
    Thanks
    75
    Thanked 4,338 Times in 4,304 Posts
    I'm surprised that this part works:
    Code:
    window.onload = function() {
      SetAction();
    }
    Because if the existing JS code had some method onload, you just wiped it out.

    Well, obviously the existing code did not have such a method.

    ************

    Re the code to convert the checkbox values to numbers:

    Mine really is quite simple, honest.
    Code:
    parseFloat( cb.value.replace(/[^\d\.]/g,"") );
    In JS, the string.replace() method takes a regular expression as the first argument.

    So mine simply says /[^\d\.]/g which means "all characters EXCEPT digits and period, for all occurrences". Meaning that I want replace to change all non-digit, non-period characters into blank strings. Essentially, wipe out all characters but digits and periods.

    So "A - $5.00" sees all charcters except "5" and "." and "0" zapped, to become simply "5.00". And then parseFloat happily converts that to a number.

    So doing the same thing as jmerker's loop, but all in a single replace.
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #8
    Senior Coder jmrker's Avatar
    Join Date
    Aug 2006
    Location
    FL
    Posts
    3,075
    Thanks
    38
    Thanked 498 Times in 492 Posts

    Arrow

    Quote Originally Posted by Old Pedant View Post
    I'm surprised that this part works:
    Code:
    window.onload = function() {
      SetAction();
    }
    Because if the existing JS code had some method onload, you just wiped it out.

    Well, obviously the existing code did not have such a method.

    ...
    My assumption was that if there were other 'onload' functions in existence,
    they would be moved to be incorporated into the new statement. Is that a bad assumption?

  • #9
    Supreme Master coder! Old Pedant's Avatar
    Join Date
    Feb 2009
    Posts
    25,171
    Thanks
    75
    Thanked 4,338 Times in 4,304 Posts
    *Assigning* to onload is a one-time thing. Just like assigning to a variable.

    But you can *attach* multiple event handlers to onload, just as you use attachEvent for other event handlers. Unfortunately, MSIE uses different code than the rest of the world to do so (why are we surprised). But it's not a big deal.

    Oh...just noticed...you are showing that in your code, already! Your addEvent( ) function is doing just that: handling the difference between MSIE and the world.

    Note that if the other code on that page is using addEvent (or equivalent) and your assignment to onload is first, then it's all going to work just fine. As I said, obviously the existing code didn't have any method conflicting with yours.

    Here. A demo:
    Code:
    <html><head>
    <script type="text/javascript">
    window.onload = function() { alert("First attachment"); }
    
    function foo()
    {
        alert("another function");
    }
    
    window.onload = foo;
    </script>
    </head>
    <body>
    See?
    </body>
    </html>
    And if you want, you could then change <body> to
    Code:
    <body onload="alert('and yet another');">
    An optimist sees the glass as half full.
    A pessimist sees the glass as half empty.
    A realist drinks it no matter how much there is.

  • #10
    Senior Coder jmrker's Avatar
    Join Date
    Aug 2006
    Location
    FL
    Posts
    3,075
    Thanks
    38
    Thanked 498 Times in 492 Posts
    Thanks for the information 'Old Pedant'.


  •  

    Posting Permissions

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