Made the app controller include the action by default. Added virtual callouts for data order and limit. Changed fields to use formatting, including a custom format for currency and id. Added a function for auto conversion from PHP variables to javascript. Fixed some minor bugs in the controllers already converted to jqGrid. Moved leases onto jqGrid.

git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605/site@118 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
abijah
2009-06-14 19:50:09 +00:00
parent 67d640b1a0
commit 92d8387e8c
10 changed files with 260 additions and 254 deletions

View File

@@ -63,11 +63,11 @@ class AppController extends Controller {
* - called by function to create an index listing * - called by function to create an index listing
*/ */
function jqGridView($action, $title) { function jqGridView($title, $action = null) {
$this->set('title', $title); $this->set('title', $title);
// The resulting page will contain a jqGrid, which will // The resulting page will contain a jqGrid, which will
// use ajax to obtain the actual data for this action // use ajax to obtain the actual data for this action
$this->set('action', $action); $this->set('action', $action ? $action : $this->params['action']);
$this->render('/elements/' . $this->params['controller']); $this->render('/elements/' . $this->params['controller']);
} }
@@ -103,13 +103,13 @@ class AppController extends Controller {
$total = ($count < 0) ? 0 : ceil($count/$limit); $total = ($count < 0) ? 0 : ceil($count/$limit);
$page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']); $page = ($params['page'] <= 1) ? 1 : (($params['page'] > $total) ? $total : $params['page']);
$start = $limit*$page - $limit; $start = $limit*$page - $limit;
$sidx = isset($params['sidx']) ? $params['sidx'] : '';
$sord = isset($params['sord']) ? ' ' . $params['sord'] : '';
// Grab the actual records taking pagination into account // Grab the actual records taking pagination into account
$query['group'] = $model->alias . '.id'; $query['group'] = $model->alias . '.id';
$query['order'] = $sidx ? $sidx . $sord : null; $query['order'] = $this->jqGridDataOrder($params,
$query['limit'] = $start . ', ' . $limit; isset($params['sidx']) ? $params['sidx'] : null,
isset($params['sord']) ? $params['sord'] : null);
$query['limit'] = $this->jqGridDataLimit($params, $start, $limit);
$query['fields'] = $this->jqGridDataFields($params); $query['fields'] = $this->jqGridDataFields($params);
$results = $this->jqGridDataRecords($params, $model, $query); $results = $this->jqGridDataRecords($params, $model, $query);
@@ -229,6 +229,17 @@ class AppController extends Controller {
return null; return null;
} }
function jqGridDataOrder(&$params, $index, $direction) {
if ($direction)
$direction = ' ' . $direction;
return $index ? $index . $direction : null;
}
function jqGridDataLimit(&$params, $start, $limit) {
return $start . ', ' . $limit;
}
function jqGridDataRecordCount(&$params, $model, $query) { function jqGridDataRecordCount(&$params, $model, $query) {
return $model->find('count', $query); return $model->find('count', $query);
} }

View File

@@ -30,9 +30,9 @@ class CustomersController extends AppController {
*/ */
function index() { $this->current(); } function index() { $this->current(); }
function current() { $this->jqGridView('current', 'Current Tenants'); } function current() { $this->jqGridView('Current Tenants'); }
function past() { $this->jqGridView('past', 'Past Tenants'); } function past() { $this->jqGridView('Past Tenants'); }
function all() { $this->jqGridView('all', 'All Tenants'); } function all() { $this->jqGridView('All Tenants', 'all'); }
/************************************************************************** /**************************************************************************

View File

@@ -1,10 +1,6 @@
<?php <?php
class LeasesController extends AppController { class LeasesController extends AppController {
var $paginate = array
('limit' => 100,
'group' => 'Lease.id',
'order' => array('Lease.movein_date' => 'DESC'));
var $sidemenu_links = var $sidemenu_links =
array(array('name' => 'Leases', 'header' => true), array(array('name' => 'Leases', 'header' => true),
@@ -28,24 +24,52 @@ class LeasesController extends AppController {
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************
* action: index * action: index / active / closed / all
* - Lists current leases * - Generate a listing of leases
*/ */
function index() { function index() { $this->all(); }
$this->active(); function active() { $this->jqGridView('Active Leases'); }
} function closed() { $this->jqGridView('Closed Leases'); }
function all() { $this->jqGridView('All Leases'); }
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************
* action: active * virtuals: jqGridData
* - Lists all active leases * - With the application controller handling the jqGridData action,
* these virutal functions ensure that the correct data is passed
* to jqGrid.
*/ */
function active() { function jqGridDataSetup(&$params) {
$leases = $this->paginate(array('Lease.close_date IS NULL')); parent::jqGridDataSetup($params);
if (!isset($params['action']))
$params['action'] = 'all';
}
function jqGridDataTables(&$params) {
return array
('link' => array('Unit' => array('fields' => array('Unit.name')),
'Customer' => array('fields' => array('Customer.name'))));
}
function jqGridDataConditions(&$params) {
$conditions = parent::jqGridDataConditions($params);
if ($params['action'] === 'active') {
$conditions[] = 'Lease.close_date IS NULL';
}
elseif ($params['action'] === 'closed') {
$conditions[] = 'Lease.close_date IS NOT NULL';
}
return $conditions;
}
function jqGridDataRecords(&$params, $model, $query) {
$leases = parent::jqGridDataRecords($params, $model, $query);
// Get the balance on each lease. // Get the balance on each lease.
foreach ($leases AS &$lease) { foreach ($leases AS &$lease) {
@@ -53,56 +77,7 @@ class LeasesController extends AppController {
$lease['Lease']['balance'] = $stats['Account']['Ledger']['balance']; $lease['Lease']['balance'] = $stats['Account']['Ledger']['balance'];
} }
$title = 'Active Leases'; return $leases;
$this->set('title', $title); $this->set('heading', $title);
$this->set('leases', $leases);
$this->render('index');
}
/**************************************************************************
**************************************************************************
**************************************************************************
* action: closed
* - Lists all closed (inactive) leases
*/
function closed() {
$leases = $this->paginate(array('Lease.close_date IS NOT NULL'));
// Get the balance on each lease.
foreach ($leases AS &$lease) {
$stats = $this->Lease->stats($lease['Lease']['id']);
$lease['Lease']['balance'] = $stats['Account']['Ledger']['balance'];
}
$title = 'Past Leases';
$this->set('title', $title); $this->set('heading', $title);
$this->set('leases', $leases);
$this->render('index');
}
/**************************************************************************
**************************************************************************
**************************************************************************
* action: all
* - Lists all leases
*/
function all() {
$leases = $this->paginate();
// Get the balance on each lease.
foreach ($leases AS &$lease) {
$stats = $this->Lease->stats($lease['Lease']['id']);
$lease['Lease']['balance'] = $stats['Account']['Ledger']['balance'];
}
$title = 'All Leases';
$this->set('title', $title); $this->set('heading', $title);
$this->set('leases', $leases);
$this->render('index');
} }

View File

@@ -1,9 +1,6 @@
<?php <?php
class UnitsController extends AppController { class UnitsController extends AppController {
var $paginate = array('limit' => 100,
'group' => 'Unit.id',
'order' => array('Unit.sort_order' => 'ASC'));
var $sidemenu_links = var $sidemenu_links =
array(array('name' => 'Units', 'header' => true), array(array('name' => 'Units', 'header' => true),
@@ -28,15 +25,15 @@ class UnitsController extends AppController {
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************
* action: index / current / past / all * action: index / unavailable / vacant / occupied / all
* - Creates a list of tenants * - Generate a listing of units
*/ */
function index() { $this->all(); } function index() { $this->all(); }
function unavailable() { $this->jqGridView('unavailable', 'Unavailable Units'); } function unavailable() { $this->jqGridView('Unavailable Units'); }
function vacant() { $this->jqGridView('vacant', 'Vacant Units'); } function vacant() { $this->jqGridView('Vacant Units'); }
function occupied() { $this->jqGridView('occupied', 'Occupied Units'); } function occupied() { $this->jqGridView('Occupied Units'); }
function all() { $this->jqGridView('all', 'All Units'); } function all() { $this->jqGridView('All Units', 'all'); }
/************************************************************************** /**************************************************************************
@@ -89,40 +86,13 @@ class UnitsController extends AppController {
return $conditions; return $conditions;
} }
function zzjqGridDataRecordCount(&$params, $model, $query) { function jqGridDataOrder(&$params, $index, $direction) {
if ($index === 'Unit.name') {
// We don't have a good way to use the query to obtain $index = 'Unit.sort_order';
// our count. The problem is that we're relying on the
// group by for the query, which will destroy the count,
// whether we omit the group by or leave it in.
// So, build a fresh query for counting.
$query['conditions'] = parent::jqGridDataConditions($params);
$count = $model->find('count',
array_merge(array('link' => array_diff_key($query['link'],
array('CurrentLease'=>1))),
array_diff_key($query, array('link'=>1))));
if ($params['action'] === 'all')
return $count;
$query['conditions'][] = 'CurrentLease.id IS NULL';
$count_past = $model->find('count', $query);
// Since we can't easily count 'current' directly, we
// can quickly derive it since 'current' customers
// are mutually exclusive to 'past' customers.
if ($params['action'] == 'current')
$count = $count - $count_past;
elseif ($params['action'] == 'past') {
$count = $count_past;
} }
return parent::jqGridDataOrder($params, $index, $direction);
return $count;
} }
/************************************************************************** /**************************************************************************
************************************************************************** **************************************************************************
************************************************************************** **************************************************************************

View File

@@ -2,22 +2,14 @@
// Define the table columns // Define the table columns
$cols = array(); $cols = array();
$cols['ID'] = array('index' => 'Customer.id', 'width' => '30', 'align' => 'center'); $cols['ID'] = array('index' => 'Customer.id', 'formatter' => 'id');
if (isset($customers[0]['ContactsCustomer'])) if (0) // REVISIT<AP>: Need to figure out how to put this in play
$cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'width' => '75', 'align' => 'left'); $cols['Relationship'] = array('index' => 'ContactsCustomer.type', 'width' => '75');
$cols['Name'] = array('index' => 'Customer.name', 'width' => '150', 'align' => 'left'); $cols['Name'] = array('index' => 'Customer.name', 'width' => '150');
$cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100', 'align' => 'left'); $cols['Last Name'] = array('index' => 'PrimaryContact.last_name', 'width' => '100');
$cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100', 'align' => 'left'); $cols['First Name'] = array('index' => 'PrimaryContact.first_name', 'width' => '100');
$cols['Leases'] = array('index' => 'lease_count', 'width' => '60', 'align' => 'center'); $cols['Leases'] = array('index' => 'lease_count', 'width' => '60');
$cols['Comment'] = array('index' => 'Customer.comment', 'width' => '300', 'align' => 'left'); $cols['Comment'] = array('index' => 'Customer.comment', 'formatter' => 'comment');
// Some of the columns should not be sortable
foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v)
$cols[$k]['sortable'] = false;
// Some of the columns should be searchable
foreach (array_intersect_key($cols, array('Last Name'=>1, 'First Name'=>1)) AS $k => $v)
$cols[$k]['search'] = true;
echo $this->element('jqGrid', echo $this->element('jqGrid',
array('jqGridColumns' => $cols)); array('jqGridColumns' => $cols));

View File

@@ -23,22 +23,75 @@ $javascript->link('jqGrid/jquery.jqGrid.js', false);
$javascript->link('jqGrid/js/jqModal', false); $javascript->link('jqGrid/js/jqModal', false);
$javascript->link('jqGrid/js/jqDnR', false); $javascript->link('jqGrid/js/jqDnR', false);
// Create the javascript code for jqGrid to create each table column // Helper function to convert PHP vars to javascript
$colModels = array(); function phpVarToJavascript($var, $name = '', $depth='', $special = false) {
foreach ($jqGridColumns AS $col) {
$col['name'] = $col['index']; // Establish a prefix to use before printing $var
$colModels[] = $prefix = $depth;
'{ ' . implode(", ",
array_map(create_function // If given a name, set it up JS style
('$k, $v', if ($name)
'return "$k:".($v===false?"false":($v===true?"true":"\'$v\'"));'), $prefix .= $name . ": ";
array_keys($col),
array_values($col))) . if (!isset($var))
'}'; return $prefix . 'null';
if (is_bool($var))
return $prefix . ($var ? "true" : "false");
if (is_numeric($var))
return $prefix . $var;
if (is_string($var)) {
// Check to see if this is a special
if ($special)
return $prefix . $var;
// OK, must just be a string after all
return $prefix . "'$var'";
}
// The only thing left that we know how to dump
// is an array. Die if we have anything else.
if (!is_array($var)) {
die;
return null;
}
// Keep a lookout for special cases, flagged by '--special'
// eg: array('name' => array('--special' => array('a' => 'one', 'b' => 'two')))
// GIVES: name: [ 'one', 'two' ]
// NOT: name: { --special: { a: 'one', b: 'two' } }
// eg: array('name' => array('--special' => 'varname'))
// GIVES: name: varname
// NOT: name: { --special: 'varname' }
if (isset($var['--special']) && count($var) == 1)
return phpVarToJavascript($var['--special'], $name, $depth, true);
// PHP array indices can be a mix of integer and string based.
// Just guess here, unless flagged as a special case.
if (isset($var[0]) || $special)
return ($prefix . "[\n"
. implode(",\n",
array_map('phpVarToJavascript',
array_values($var),
array(),
array_fill(0, count($var), $depth.' ')
))
. "\n$depth]");
return ($prefix . "{\n"
. implode(",\n",
array_map('phpVarToJavascript',
array_values($var), array_keys($var),
array_fill(0, count($var), $depth.' ')
))
. "\n$depth}");
} }
// Save just the column indices (fields)
$colFields= array_map(create_function('$col', 'return $col["index"];'), $jqGridColumns);
// Define the URL to fetch data from. // Define the URL to fetch data from.
// To prevent having to keep the controller and the view // To prevent having to keep the controller and the view
@@ -51,6 +104,57 @@ $url = $html->url(array('action' => 'jqGridData',
'debug' => 0, 'debug' => 0,
)); ));
// Create extra parameters that jqGrid will pass to our
// controller whenever data is requested. 'action' will
// ensure that the controller provides the correct subset
// of data, and 'fields' will allow it to return only the
// requested fields, and in the right order. Since fields
// is a complex structure (an array), we'll need to
// serialize it first for transport over HTTP.
$postData = array('action' => $action,
'fields' => serialize(array_map(create_function('$col',
'return $col["index"];'),
$jqGridColumns)));
// Perform column customizations.
// This will largely be based off of the 'formatter' parameter,
// but could be on any pertinent condition.
foreach ($jqGridColumns AS &$col) {
$default = array();
// Make sure every column has a name
$default['name'] = $col['index'];
// Perform customization based on formatter
if (isset($col['formatter'])) {
if ($col['formatter'] === 'id') {
// Switch currency over to our own custom formatting
$col['formatter'] = array('--special' => 'idFormatter');
$default['width'] = 50;
$default['align'] = 'center';
}
elseif ($col['formatter'] === 'currency') {
// Switch currency over to our own custom formatting
$col['formatter'] = array('--special' => 'currencyFormatter');
$default['width'] = 80;
$default['align'] = 'right';
}
elseif ($col['formatter'] === 'date') {
$default['formatoptions'] = array('newformat' => 'm/d/Y');
$default['width'] = 90;
$default['align'] = 'center';
}
elseif ($col['formatter'] === 'comment') {
$default['width'] = 300;
$default['sortable'] = false;
}
}
$col = array_merge($default, $col);
}
// OK, now that everything is in place, get out of PHP mode, // OK, now that everything is in place, get out of PHP mode,
// and add the javascript code (along with a touch of HTML) // and add the javascript code (along with a touch of HTML)
// to kick this thing off. // to kick this thing off.
@@ -59,25 +163,34 @@ $url = $html->url(array('action' => 'jqGridData',
<script type="text/javascript"><!-- <script type="text/javascript"><!--
jQuery(document).ready(function(){ jQuery(document).ready(function(){
jQuery('#<?php echo $gridId; ?>').jqGrid({ currencyFormatter = function(el, cellval, opts) {
url: '<?php echo $url; ?>', $(el).html(fmtCurrency(cellval));
datatype: 'xml', }
mtype: 'GET',
postData: { action: '<?php echo $action; ?>', idFormatter = function(el, cellval, opts) {
fields: '<?php echo serialize($colFields); ?>' }, $(el).html('#'+cellval);
colNames: [ '<?php echo implode("', '", array_keys($jqGridColumns)); ?>' ], }
colModel: [ <?php echo "\n " . implode(",\n ", $colModels); ?> ],
pager: jQuery('#<?php echo $gridId; ?>-pager'), jQuery('#<?php echo $gridId; ?>').jqGrid(
height: '<?php echo $height; ?>', <?php
rowNum: <?php echo $limit; ?>, echo phpVarToJavascript(array('mtype' => 'GET',
rowList: [<?php echo implode(",",$limitOptions); ?>], 'datatype' => 'xml',
/* sortname: 'Customer.id', */ 'url' => $url,
/* sortorder: "ASC", */ 'postData' => $postData,
viewrecords: true, 'colNames' => array_keys($jqGridColumns),
imgpath: '<?php echo $imgpath; ?>', 'colModel' => array('--special' => $jqGridColumns),
caption: <?php echo $caption ? "'$caption'" : "null"; ?>, /* 'sortname' => 'id', */
/* toolbar : [true,"bottom"], */ /* 'sortorder' => 'ASC', */
}); 'height' => $height,
'rowNum' => $limit,
'rowList' => $limitOptions,
'caption' => $caption,
'imgpath' => $imgpath,
'viewrecords' => true,
'pager' => array('--special' => "jQuery('#{$gridId}-pager')"),
//'toolbar' => array(true,"bottom"),
)); ?>
);
/* jQuery('#t_<?php echo $gridId; ?>').height(25).hide() */ /* jQuery('#t_<?php echo $gridId; ?>').height(25).hide() */
/* .filterGrid('#<?php echo $gridId; ?>', { */ /* .filterGrid('#<?php echo $gridId; ?>', { */
@@ -112,6 +225,7 @@ jQuery(document).ready(function(){
<table id="<?php echo $gridId; ?>" class="scroll"></table> <table id="<?php echo $gridId; ?>" class="scroll"></table>
<div id="<?php echo $gridId; ?>-pager" class="scroll" style="text-align:center;"></div> <div id="<?php echo $gridId; ?>-pager" class="scroll" style="text-align:center;"></div>
<div id="debug"></div>
<script type="text/javascript"><!-- <script type="text/javascript"><!--

View File

@@ -1,85 +1,16 @@
<?php /* -*- mode:PHP -*- */ <?php /* -*- mode:PHP -*- */
if (isset($heading)) // Define the table columns
echo $heading; $cols = array();
elseif (!isset($caption)) $cols['Lease'] = array('index' => 'Lease.number', 'formatter' => 'id');
echo '<h2>'.__('Leases',true).'</h2>'; $cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'center');
$cols['Customer'] = array('index' => 'Customer.name', 'width' => '150');
$cols['Signed'] = array('index' => 'Lease.lease_date', 'formatter' => 'date');
$cols['Move-In'] = array('index' => 'Lease.movein_date', 'formatter' => 'date');
$cols['Move-Out'] = array('index' => 'Lease.moveout_date', 'formatter' => 'date');
$cols['Balance'] = array('index' => 'Lease.balance', 'formatter' => 'currency');
$cols['Comment'] = array('index' => 'Lease.comment', 'formatter' => 'comment');
$headers = array_merge(array('Lease'), echo $this->element('jqGrid',
isset($leases[0]['Unit']) array('jqGridColumns' => $cols));
? array('Unit')
: array('Customer'),
array('Signed', 'Move-In', 'Move-Out', 'Balance', 'Comment'));
$column_class = array();
foreach (array_intersect($headers, array('Lease', 'Unit')) AS $k => $v) {
$column_class[$k] = 'id';
}
foreach (array_intersect($headers, array('Balance')) AS $k => $v) {
$column_class[$k] = 'currency';
}
foreach (array_intersect($headers, array('Comment')) AS $k => $v) {
$column_class[$k] = 'slack';
}
if (isset($paginator)) {
echo $paginator->counter(array('format' => __('Page %page% of %pages%, showing %current% records (%start% - %end%) of %count% total', true)));
$headers = array_merge(array($paginator->sort('Lease')),
isset($leases[0]['Unit'])
? array($paginator->sort('Unit', 'Unit.id'))
: array($paginator->sort('Customer.id')),
array($paginator->sort('Signed', 'lease_date'),
$paginator->sort('Move-In', 'movein_date'),
$paginator->sort('Move-Out', 'moveout_date'),
$paginator->sort('balance'),
$paginator->sort('comment')));
}
$rows = array();
foreach($leases AS $lease) {
$unit = $customer = null;
if (isset($lease['Unit']))
$unit = $lease['Unit'];
else
$customer = $lease['Customer'];
if (isset($lease['Lease']))
$lease = $lease['Lease'];
$rows[] = array_merge(array($html->link('#'.$lease['number'],
array('controller' => 'leases',
'action' => 'view',
$lease['id']))),
isset($unit)
? array($html->link($unit['name'],
array('controller' => 'units',
'action' => 'view',
$unit['id'])))
: array($html->link($customer['name'],
array('controller' => 'customers',
'action' => 'view',
$customer['id']))),
array(FormatHelper::date($lease['lease_date']),
FormatHelper::date($lease['movein_date']),
FormatHelper::date($lease['moveout_date']),
FormatHelper::currency($lease['balance']),
$lease['comment']));
}
echo $this->element('table',
array('class' => 'item lease list',
'caption' => isset($caption) ? $caption : null,
'headers' => $headers,
'rows' => $rows,
'column_class' => $column_class));
if (isset($paginator)) {
echo('<div class="paging">' . "\n");
echo $paginator->prev('<< '.__('previous', true), array(), null, array('class'=>'disabled'));
echo(' | ');
echo $paginator->numbers();
echo(' | ');
echo $paginator->next(__('next', true).' >>', array(), null, array('class'=>'disabled'));
echo('</div>' . "\n");
}

View File

@@ -2,15 +2,11 @@
// Define the table columns // Define the table columns
$cols = array(); $cols = array();
$cols['ID'] = array('index' => 'Unit.id', 'width' => '30', 'align' => 'center'); $cols['ID'] = array('index' => 'Unit.id', 'formatter' => 'id');
$cols['Unit'] = array('index' => 'Unit.name', 'width' => '50', 'align' => 'left'); $cols['Unit'] = array('index' => 'Unit.name', 'width' => '50');
$cols['Size'] = array('index' => 'UnitSize.name', 'width' => '75', 'align' => 'left'); $cols['Size'] = array('index' => 'UnitSize.name', 'width' => '75');
$cols['Status'] = array('index' => 'Unit.status', 'width' => '75', 'align' => 'left'); $cols['Status'] = array('index' => 'Unit.status', 'width' => '75');
$cols['Comment'] = array('index' => 'Unit.comment', 'width' => '400', 'align' => 'left'); $cols['Comment'] = array('index' => 'Unit.comment', 'formatter' => 'comment');
// Some of the columns should not be sortable
foreach (array_intersect_key($cols, array('Comment'=>1)) AS $k => $v)
$cols[$k]['sortable'] = false;
echo $this->element('jqGrid', echo $this->element('jqGrid',
array('jqGridColumns' => $cols)); array('jqGridColumns' => $cols));

View File

@@ -1,3 +0,0 @@
<div class="leases index">
<?php echo $this->element('leases', array('heading' => '<h2>'.$heading.'</h2>')) ?>
</div>

View File

@@ -114,3 +114,23 @@ $("#debug").append(htmlEncode(html));
function removeElement(elem_id) { function removeElement(elem_id) {
$('#'+elem_id).remove(); $('#'+elem_id).remove();
} }
function fmtCurrency(amount) {
if (amount == null || isNaN(amount))
return '-';
// Get rid of any extraneous characters, determine
// the sign, and round to the nearest cent.
amount = amount.toString().replace(/\$|\,/g,'');
sign = (amount == (amount = Math.abs(amount)));
amount = (amount+0.0000000001).toFixed(2);
// Insert thousands separator
while (amount != (amount = amount.replace(/(\d)(\d\d\d[.,])/, "$1,$2")));
// Return formatted amount
return (sign?'$':'($') + amount + (sign?'':')');
}