views:

461

answers:

5

Ok, considering the regular expressions aren't working properly and there are no errors, I'm going to try and use the money mask.

The goal is still to only allow numeric characters and a decimal. With maskMoney, that does the work for you.

Also, I need to be able to successfully calculate each cell.

As of right now, the masks are working good, but I'm no longer able to calculate. This is where I'm troubled.

JQuery and JavaScript code:


<script type="text/javascript" language="javascript">
    $(document).ready(function(){
     $('.date').mask("99/99/9999");
     $('.account').mask("99-9-999999-9999");
     /*calcuating the vertical and horizontal inputs*/

     $('.R26').attr("disabled", "disabled");

 $('.calc').maskMoney({symbol: ""});
 $('.R25').unmaskMoney();
 $('.R18').unmaskMoney();

 $('input.description').focus(function(){
  if($(this).val()=="Enter text here"){
   $(this).val(" ");
  }

  else{
   $(this).val($(this).val());
  }
 });
 $('input.description').blur(function(){
  if($(this).val()==" "){
   $(this).val("Enter text here");
  }    
 });

$('.calc').keyup(function(){
 var classArray = $(this).attr('class').split(' ');
 //Personal gas expense
 $('.gasamount').sum("change", "#totals4");
 var num = $(this).attr("id").replace(/[A-Za-z$,-]/g, "");
 $('#gasmoney'+num).val(<cfoutput>#mileage#</cfoutput> * $(this).val());
 $('.gasmoney').sum("change", "#totals5");
 //////////////////////

 //Sum of each cell
 $.each(classArray, function(){
  $('.'+this).sum("change", ".ttl"+this);
 });
 //Finding the grandtotal
 var grandTotal = $('.row26').parent().children('td:last').children('input');
 var sum = $('.row25').parent().children('td').children('.calc').sum();
 grandTotal.val(Number(sum).toFixed(2));
});

ColdFusion and HTML code:

#labels[r]#

<cfloop from="1" to="7" index="i">

 <td id="Day#i#" class="row#r# col#i#">
  <cfif r EQ 1>#Left(DayOfWeekAsString(i),3)#<cfelse><cfif r EQ 2>
  <input type="text" class="date-mask" /><cfelse>
  <input type="text" 
  <cfif labels[r] EQ "Personal Car: Mileage ##"> id="gasamount#i#" <cfelseif labels[r] EQ "Personal Car: Mileage $">id="gasmoney#i#" </cfif><cfif labels[r] EQ "Daily Totals">id="dailytotals#i#"</cfif>
   class="<cfif labels[r] EQ "Personal Car: Mileage ##">gasamount<cfelse><cfif labels[r] NEQ "Daily Totals">C#i#</cfif></cfif>
   <cfif labels[r] EQ "Personal Car: Mileage $">gasmoney<cfelse>calc R#r#</cfif>
   <cfif labels[r] EQ "Daily Totals">ttlC#i#</cfif>"
    <cfif labels[r] EQ "Daily Totals" OR labels[r] EQ "Personal Car: Mileage $">readonly="readonly"</cfif>
     /></cfif>
     </cfif>
 </td>


</cfloop>

 <td class="totals"><cfif r EQ 1>Total<cfelse><input type="text" id="totals" class="ttlR#r#" readonly="readonly" /></cfif></td>

I've had similar questions with the same application, but this is in fact not a duplicate(in case you think it is.).

The '.'+this is an object created by the array. I used cfloops to create a large table, and added multiple classes. Had to break up the multiple classes into an array, and then was able to select each class as its own.

A: 

Dollar ($) is used to mark the end of a regex search. /[A-Za-z$-,]/ may not work well. Escape the dollar with a backslash (\$).

mcandre
Thanks for the little tip, but I use the same one on other applications and it works like a charm! I added that and still works though. Probably the better approach!
Michael Stone
That's plain wrong. The `$` has no special meaning in a character class, so escaping it won't change anything.
Tomalak
A: 

EDIT: My original answer was partially correct, in that it changed the value, but it did not fix a more serious bug which I will now explain.

The reason my original fix causes ever cell to have the same value is because the jQuery $ method returns every element which matches the given selector. However, calling val() will only get you the value of the first matched element, but setting the value by calling val(value) will set the value of every matched element.

The solution is to do the replace above the each(), which will then only sanitize a single element (the this). If you also want to sanitize the totals cells, then you would do that in the each() and use ".ttl" + this as the selector instead of this.

$('.calc').keyup(function(){
    var classArray = $(this).attr('class').split(' ');

    //Sanitize out here, so we only affect one element.
    var singleCellVal = $(this).val()
    singleCellVal.replace(/[A-Za-z$-,]/g, "");
    $(this).val(singleCellVal);

    $.each(classArray, function(){
        var totalsum = $('.'+this).sum();
        $('.ttl'+this).val(Number(totalsum).toFixed(2));
    });

    //Finding the grandtotal
    var grandTotal = $('.row26').parent().
        children('td:last').children( 'input');
    var sum = $('.row25').parent().children( 'td').children('.calc').sum();
    grandTotal.val(Number(sum).toFixed(2));
});

What you want is

var value = $('.'+this).val();
value.replace(/[A-Za-z$-,]/g, "");
$('.' + this).val(value);

The $ in the character class is fine, most metacharacters in regex are not special within character classes. However, the "$-," will match any characters that are "between" $ and ,. I assume this is what you want but if you only want to match $ and , and - then you should change that part to "$,-" (i.e. /[A-Za-z$,-]/g). A - at the end of a character class will match the -, anywhere else is seen as a range unless you escape it (\-).

Sean Nyman
Hi Sean. I actually was using the exact same method as you and this is what I was returning.http://mercury.hamilton.edu/devmpstone/forms-pdf/employee-expense-report.cfmIt's pretty interesting, never seen it before. Hope you've got an idea, I don't at the moment!
Michael Stone
I tried your edited version, and this time I return nothing. Thank you for trying to help out though. If I find a solution, I'll be sure to post it on here.
Michael Stone
+2  A: 

It's highly likely that you want

.replace(/[A-Za-z$,-]/g, "")

instead of

.replace(/[A-Za-z$-,]/g, "")

The latter expression matches:

  • all characters from "A" to "Z"
  • all characters from "a" to "z"
  • all characters from "$" to "," (there is such a range, but I'm not sure if that is your actual intent)

The former expression (note the shifted dash) matches:

  • all characters from "A" to "Z"
  • all characters from "a" to "z"
  • the character "$"
  • the character ","
  • the character "-"

The dash has a special meaning in character classes, it defines a range. If you want to match a literal dash, move it to the end (or the start) of the character class.

EDIT: Apart from that you seem to want to set the value. Setting through val() works by passing the new value into the function:

$dotThis = $('.' + this);
$dotThis.val($dotThis.val().replace(/[A-Za-z$-,]/g, ""));

This statement:

$('.'+this).val().replace(/[A-Za-z$-,]/g, "");

creates a replaced string and immediately throws it away.

Tomalak
Hi Tom, I've tried using your fix, and still no result. I think it might be a matter of where I place the replace in the event. Maybe outside of the event. Hmm.
Michael Stone
See my updated answer.
Tomalak
This is where I get confused. I always get this point and then have this happen. Take a look. I've changed the event listener to keyup so it's more apparent.
Michael Stone
Look. `val()` is a function, not a property. It returns a string. You can change that returned string all right, but that will *not* change the original value of the element (!). If you want to *set* a value, you need to call it with a parameter: `.val(newValue);`. That's what I do, and you don't.
Tomalak
My apologies. I've been commenting pieces of code out and removing pieces, finding breaks and fixing things. I did use that to begin with, but not with the code I posted. It's not working correctly because of the looped array. Trying a different approach to correct these errors.
Michael Stone
+1 for recognizing the range.
Gumbo
+1  A: 

Might be a bit simplistic but why not use the negation? Perl syntax: Not sure about javascript.

Why not: m/([^0-9]+)//g

Matches between zero and nine

lungic
I've tried that already though and I get the same result. Using JS, not Perl.
Michael Stone
A: 

Ok. So I figured it out on my own.

Using the maskMoney(), I am able to control what characters are entered and still able to correctly calculate the table.

All I had to do to fix the calculations was to unmask the .gasamount:

    $('.gasamount').unmaskMoney();

This is what fixed the calculation problems. ^^ The mask was causing problems for the total of the 2 rows and those 2 rows caused the calculations to break.


    $('.calc').maskMoney({symbol: ""});
    $('.R25').unmaskMoney();
    $('.R18').unmaskMoney();

   $('.calc').keyup(function(){
    var classArray = $(this).attr('class').split(' ');
    //Personal gas expense
    $('.gasamount').sum("change", "#totals4");
    var num = $(this).attr("id").replace(/[A-Za-z$,-]/g, "");
    $('#gasmoney'+num).val(<cfoutput>#mileage#</cfoutput> * $(this).val());
    $('.gasmoney').sum("change", "#totals5");
    //////////////////////

    //Sum of each cell
    $.each(classArray, function(){
     $('.'+this).sum("change", ".ttl"+this);
    });
    //Finding the grandtotal
    var grandTotal = $('.row26').parent().children('td:last').children('input');
    var sum = $('.row25').parent().children('td').children('.calc').sum();
    grandTotal.val(Number(sum).toFixed(2));
   });

Everyone that tried to help, thank you for taking the time!

If anyone would like to use this example or the code for future applications, feel free to comment and let me know and I can setup a different page with an example and instructions and the source.

Michael Stone