diff options
Diffstat (limited to 'httemplate/elements')
-rw-r--r-- | httemplate/elements/auto-table.html | 310 | ||||
-rw-r--r-- | httemplate/elements/contact.html | 2 | ||||
-rw-r--r-- | httemplate/elements/menu.html | 97 | ||||
-rw-r--r-- | httemplate/elements/searchbar-address2.html | 2 | ||||
-rw-r--r-- | httemplate/elements/searchbar-cust_bill.html | 2 | ||||
-rw-r--r-- | httemplate/elements/searchbar-cust_main.html | 2 | ||||
-rw-r--r-- | httemplate/elements/searchbar-cust_svc.html | 2 | ||||
-rw-r--r-- | httemplate/elements/searchbar-prospect.html | 2 | ||||
-rw-r--r-- | httemplate/elements/searchbar-ticket.html | 2 | ||||
-rw-r--r-- | httemplate/elements/select-did.html | 69 | ||||
-rw-r--r-- | httemplate/elements/select-mib-popup.html | 186 | ||||
-rw-r--r-- | httemplate/elements/select-phonenum.html | 10 | ||||
-rw-r--r-- | httemplate/elements/select-region.html | 88 | ||||
-rw-r--r-- | httemplate/elements/select-terms.html | 2 | ||||
-rw-r--r-- | httemplate/elements/standardize_locations.js | 19 | ||||
-rw-r--r-- | httemplate/elements/xmlhttp.html | 32 |
16 files changed, 601 insertions, 226 deletions
diff --git a/httemplate/elements/auto-table.html b/httemplate/elements/auto-table.html index 49222745a..9aff94e67 100644 --- a/httemplate/elements/auto-table.html +++ b/httemplate/elements/auto-table.html @@ -1,166 +1,180 @@ <%doc> - -Example: -<% include('/elements/auto-table.html', - - ### - # required - ### - - 'header' => [ '#', 'Item', 'Amount' ], - 'fields' => [ 'id', 'name', 'amount' ], - - ### - # highly recommended - ### - - 'size' => [ 4, 12, 8 ], - 'maxl' => [ 4, 12, 8 ], - 'align' => [ 'right', 'left', 'right' ], - - ### - # optional - ### - - 'data' => [ [ 1, 'Widget', 25 ], - [ 12, 'Super Widget, 7 ] ], - #or - 'records' => [ qsearch('item', { } ) ], - # or any other array of FS::Record objects - - 'select' => [ '', - [ 1 => 'option 1', - 2 => 'option 2', ... - ], # options for second field - '' ], - - 'prefix' => 'mytable_', -) %> - -Values will be passed through as "mytable_id1", etc. +(within a form) +<table> +<tr> + <th>Field 1</th> + <th>Field 2</th> +</tr> +<tr id="mytemplate"> + <td><input type="text" name="field1"></td> + <td><select name="field2">...</td> + ... +</tr> +</table> +<& /elements/auto-table.html, + table => 'mytable', + template_row = 'mytemplate', + rows => [ + { field1 => 'foo', field2 => 'CA', ... }, + { field1 => 'bar', field2 => 'TX', ... }, ... + ], +&> + + or if you prefer: +... + fieldorder => [ 'field1', 'field2', ... ], + rows => [ + [ 'foo', 'CA' ], + [ 'bar', 'TX' ], + ], + +In the process/ handler, something like: +my @rows; +my %vars = $cgi->Vars; +for my $k ( keys %vars ) { + $k =~ /^${pre}magic(\d+)$/ or next; + my $rownum = $1; + # find all submitted names ending in this rownum + my %thisrow = + map { $_ => $vars{$_} } + grep /^(.*[\d])$rownum$/, keys %vars; + $thisrow->{num} = delete $thisrow{"${pre}magic$rownum"}; + push @rows, $thisrow; +} </%doc> - -<TABLE ID="<% $prefix %>AutoTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0> - <TR> -% foreach (@header) { - <TH><% $_ %></TH> -% } - </TR> -% my $row = 0; -% for ( $row = 0; $row < scalar @data; $row++ ) { - <TR> -% my $col = 0; -% for ( $col = 0; $col < scalar @fields; $col++ ) { -% my $id = $prefix . $fields[$col]; -% # don't suffix rownum in the final, blank row -% $id .= $row if $row < (scalar @data) - 1; - <TD> -% my @o = @{ $select[$col] }; -% if( @o ) { - <SELECT NAME="<% $id %>" ID="<% $id %>"> -% while(@o) { -% my $val = shift @o; - <OPTION VALUE=<% $val %><% -$val eq $data[$row][$col] ? ' SELECTED' : ''%>><% shift @o %></OPTION> -% } - </SELECT> -% } -% else { - <INPUT TYPE = "text" - NAME = "<% $id %>" - ID = "<% $id %>" - SIZE = <% $size[$col] %> - MAXLENGTH = <% $maxl[$col] %> - STYLE = "text-align:<% $align[$col] %>" - VALUE = "<% $data[$row][$col] %>" -% if( $opt{'autoadd'} ) { - onchange = "possiblyAddRow(this);" -% } - > - </TD> -% } -% } - <TD> - <IMG SRC = "<% "${p}images/cross.png" %>" - ALT = "X" - onclick = "deleteRow(this);" - > - </TD> - </TR> -% } -</TABLE> -% if( !$opt{'autoadd'} ) { -<INPUT TYPE="button" VALUE="Add" onclick="<% $prefix %>addRow();"><BR> -% } - -<SCRIPT TYPE="text/javascript"> - var <% $prefix %>rownum = <% $row %>; - var <% $prefix %>table = document.getElementById('<% $prefix %>AutoTable'); - // last row is initially blank, clone it and remove it - var <% $prefix %>_blank = - <% $prefix %>table.rows[<% $prefix %>table.rows.length-1].cloneNode(true); -% if( !$opt{'autoadd'} ) { - <% $prefix %>table.deleteRow(<% $prefix %>table.rows.length-1); -% } - - - - function rownum_of(obj) { - return (obj.parentNode.parentNode.sectionRowIndex); +<tbody id="<%$pre%>autotable"></tbody> +<script type="text/javascript"> +var <%$pre%>template; +var <%$pre%>tbody; +var <%$pre%>next_rownum; +var <%$pre%>set_rownum; +var <%$pre%>addRow; +var <%$pre%>deleteRow; +var <%$pre%>fieldorder = <% to_json($fieldorder) %>; + +function <%$pre%>possiblyAddRow_factory(obj) { + var callback = obj.onchange; + return function() { + if ( obj.rownum == <%$pre%>tbody.lastChild.rownum ) { + // then this is the last row, and it's being changed, so spawn a new row + <%$pre%>addRow(); + } + if ( callback ) { + callback.apply(obj); + } } +} - function <% $prefix %>possiblyAddRow(obj) { - if ( <% $prefix %>rownum == rownum_of(obj) ) { - <% $prefix %>addRow(); +function <%$pre%>set_rownum(obj, rownum) { + obj.rownum = rownum; + if ( obj.id ) { + obj.id = obj.id + rownum; + } + if ( obj.name ) { + obj.name = obj.name + rownum; + // also, in this case it's a form field that will be part of the record + // so set up an onchange handler + obj.onchange = <%$pre%>possiblyAddRow_factory(obj); + } + for (var i = 0; i < obj.children.length; i++) { + if ( obj.children[i] instanceof Node ) { + <%$pre%>set_rownum(obj.children[i], rownum); } } +} - function <% $prefix %>addRow() { - var row = <% $prefix %>table.insertRow(-1); - var cells = <% $prefix %>_blank.cells; - for (i=0; i<cells.length; i++) { - var node = row.appendChild(cells[i].cloneNode(true)); - var input = node.children[0]; - input.id = input.id + row.sectionRowIndex; - input.name = input.name + row.sectionRowIndex; +function <%$pre%>addRow(data) { + // duplicate the node + // warning: cloneNode doesn't clone event handlers that were set through + // the DOM + // if 'data' is an object, prepopulate the row's fields with the object's + // elements + // returns the rownum of the new row + var row = <%$pre%>template.cloneNode(true); + <%$pre%>tbody.appendChild(row); + var this_rownum = <%$pre%>next_rownum; + <%$pre%>set_rownum(row, this_rownum); + if(data instanceof Array) { + for (i = 0; i < data.length && i < <%$pre%>fieldorder.length; i++) { + var el = document.getElementsByName(<%$pre%>fieldorder[i] + this_rownum)[0]; + if (el) { + el.value = data[i]; + } + } + } else if (data instanceof Object) { + for (var field in data) { + var el = document.getElementsByName(field + this_rownum)[0]; + if (el) { + el.value = data[field]; +% # doesn't work for checkbox + } } - <% $prefix %>rownum++; + } // else nothing + <%$pre%>next_rownum++; + return this_rownum; +} + +function <%$pre%>deleteRow(rownum) { + if ( rownum == <%$pre%>tbody.lastChild.rownum ) { + // if this is the last row, spawn another one after it + <%$pre%>addRow(); } + var r = document.getElementById('<%$pre%>row' + rownum); + <%$pre%>tbody.removeChild(r); +} - function deleteRow(obj) { - if(<% $prefix %>rownum == rownum_of(obj)) { - <% $prefix %>addRow(); - } - <% $prefix %>table.deleteRow(rownum_of(obj)); - <% $prefix %>rownum--; - return(false); +function <%$pre%>init() { + <%$pre%>template = document.getElementById(<% $template_row |js_string%>); + <%$pre%>tbody = document.getElementById('<%$pre%>autotable'); + <%$pre%>next_rownum = <%$pre%>template.sectionRowIndex; + // detach the template row + var table = <%$pre%>template.parentNode; + table.removeChild(<%$pre%>template); + // give it an id + <%$pre%>template.id = <%$pre |js_string%> + 'row'; + // and a magic identifier so we know it's been submitted + var magic = document.createElement('INPUT'); + magic.setAttribute('type', 'hidden'); + magic.setAttribute('name', '<%$pre%>magic'); + magic.value = '1'; + // and a delete button +%# should this be enclosed in an actual <button> for aesthetics? + var delete_button = document.createElement('IMG'); + delete_button.id = 'delete_button'; + delete_button.src = '<%$fsurl%>images/cross.png'; + delete_button.alt = 'X'; + // use an inline string for this so that it will be cloned properly + delete_button.setAttribute('onclick', "<%$pre%>deleteRow(this.rownum);"); + var delete_cell = document.createElement('TD'); + delete_cell.appendChild(delete_button); + delete_cell.appendChild(magic); // it has to go somewhere + <%$pre%>template.appendChild(delete_cell); + + // preload rows + var rows = <% to_json(\@rows) %>; + for (var i = 0; i < rows.length; i++) { + <%$pre%>addRow(rows[i]); } -</SCRIPT> + <%$pre%>addRow(); +} +<%$pre%>init(); +</script> <%init> my %opt = @_; - -my @header = @{ $opt{'header'} }; -my @fields = @{ $opt{'fields'} }; -my @data = (); -if($opt{'data'}) { - @data = @{ $opt{'data'} }; -} -elsif($opt{'records'}) { - foreach my $rec (@{ $opt{'records'} }) { - push @data, [ map { $rec->getfield($_) } @fields ]; +my $pre = ''; +$pre = $opt{'table'} . '_' if $opt{'table'}; +my $template_row = $opt{'template_row'} + or die "auto-table requires template_row\n"; # a DOM id + +# rows that we will preload, as hashrefs of name => value +my @rows = @{ $opt{'data'} || [] }; +foreach (@rows) { + # allow an array of FS::Record objects to be passed + if ( blessed($_) and $_->isa('FS::Record') ) { + $_ = $_->hashref; } } -# else @data = (); -push @data, [ map {''} @fields ]; # make a blank row - -my $prefix = $opt{'prefix'}; -my @size = $opt{'size'} ? @{ $opt{'size'} } : (map {16} @fields); -my @maxl = $opt{'maxl'} ? @{ $opt{'maxl'} } : @size; -my @align = $opt{'align'} ? @{ $opt{'align'} } : (map {'right'} @fields); -my @select = @{ $opt{'select'} || [] }; -foreach (0..scalar(@fields)-1) { - $select[$_] ||= []; -} +my $fieldorder = $opt{'fieldorder'} || []; </%init> diff --git a/httemplate/elements/contact.html b/httemplate/elements/contact.html index b3e535344..490ba2303 100644 --- a/httemplate/elements/contact.html +++ b/httemplate/elements/contact.html @@ -15,7 +15,7 @@ <% ($contact_class->classnum == $classnum) ? 'SELECTED' : '' %> ><% $contact_class->classname |h %> % } - <SELECT><BR> + </SELECT><BR> <FONT SIZE="-1">Type</FONT> </TD> % } else { diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index bfbc179b9..4e6109687 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -130,6 +130,8 @@ tie my %report_invoices, 'Tie::IxHash', 'Open invoices' => [ \%report_invoices_open, 'Open invoices' ], 'All invoices' => [ $fsurl. 'search/cust_bill.html?date', 'List all invoices' ], 'Advanced invoice reports' => [ $fsurl.'search/report_cust_bill.html', 'by agent, date range, etc.' ], + 'separator' => '', + 'Line items' => [ $fsurl. 'search/report_cust_bill_pkg.html', 'Individual line item detail' ], ; tie my %report_discounts, 'Tie::IxHash', @@ -231,13 +233,13 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) { } tie my %report_packages, 'Tie::IxHash'; -if ( $curuser->access_right('Edit package definitions') - || $curuser->access_right('Edit global package definitions') - ) -{ - $report_packages{'Package definitions (by # active)'} = [ $fsurl.'browse/part_pkg.cgi?active=1', 'Package definitions by number of active packages' ]; - $report_packages{'separator'} = ''; -} +$report_packages{'Package definitions (by # active)'} = [ $fsurl.'browse/part_pkg.cgi?active=1', 'Package definitions by number of active packages' ] + if $curuser->access_right('Edit package definitions') + || $curuser->access_right('Edit global package definitions'); +$report_packages{'Package Costs Report'} = [ $fsurl.'graph/report_cust_pkg_cost.html', 'Package setup and recurring costs graph' ] + if $curuser->access_right('Financial reports'); +$report_packages{'separator'} = '' + if keys %report_packages; if ( $curuser->access_right('Financial reports') ) { $report_packages{'Package churn'} = [ $fsurl.'graph/report_cust_pkg.html', 'Orders, suspensions and cancellations summary graph' ]; $report_packages{'separator2'} = ''; @@ -292,6 +294,11 @@ tie my %report_ticketing, 'Tie::IxHash', 'Advanced ticket reports' => [ $fsurl.'rt/Search/Build.html?NewQuery=1', 'List tickets by any criteria' ], ; +tie my %report_employees, 'Tie::IxHash', + 'Employee Commission Report' => [ $fsurl.'search/report_employee_commission.html', '' ], + 'Employee Audit Report' => [ $fsurl.'search/report_employee_audit.html', 'Employee audit report' ], +; + tie my %report_bill_event, 'Tie::IxHash', 'All billing events' => [ $fsurl.'search/report_cust_event.html', 'All billing events for a date range' ], 'Billing event errors' => [ $fsurl.'search/report_cust_event.html?failed=1', 'Failed credit cards, processor or printer problems, etc.' ], @@ -313,22 +320,32 @@ $report_payments{'Unapplied Payment Aging'} = [ $fsurl.'search/report_unapplied_ $report_payments{'Deleted Payments / Payment history table'} = [ $fsurl.'search/report_h_cust_pay.html', 'Deleted payments / payment history table' ] if $conf->exists('payment-history-report'); +tie my %report_credits, 'Tie::IxHash', + 'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ], + 'Credit application detail' => [ $fsurl.'search/report_cust_credit_bill_pkg.html', 'Line item application detail' ], + 'Unapplied Credits' => [ $fsurl.'search/report_cust_credit.html?unapplied=1', 'Unapplied credit report (by type and/or date range)' ], +; + +tie my %report_refunds, 'Tie::IxHash', + 'Refund Report' => [ $fsurl.'search/report_cust_refund.html', 'Refund report (by type and/or date range)' ], + 'Unapplied Refunds' => [ $fsurl.'search/report_cust_refund.html?unapplied=1', 'Unapplied refund report (by type and/or date range)' ], +; + +tie my %report_sales, 'Tie::IxHash', + 'Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time.html', 'Sales, credits and receipts summary graph' ], + 'Daily Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time_daily.html', 'Sales, credits and receipts (broken down by day) summary graph' ], + 'Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg.html', 'Sales report and graph (by agent, package class and/or date range)' ], + 'Rated Call Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg_detail.html', 'Sales report and graph (by agent, package class, usage class and/or date range)' ], + 'Sales With Advertising Source' => [ $fsurl.'search/report_cust_bill_pkg_referral.html' ], +; + tie my %report_financial, 'Tie::IxHash'; -if($curuser->access_right('Financial reports')) { +if( $curuser->access_right('Financial reports') ) { %report_financial = ( - 'Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time.html', 'Sales, credits and receipts summary graph' ], - 'Daily Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time_daily.html', 'Sales, credits and receipts (broken down by day) summary graph' ], - 'Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg.html', 'Sales report and graph (by agent, package class and/or date range)' ], - 'Rated Call Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg_detail.html', 'Sales report and graph (by agent, package class, usage class and/or date range)' ], - 'Sales With Advertising Source' => [ $fsurl.'search/report_cust_bill_pkg_referral.html' ], - 'Employee Commission Report' => [ $fsurl.'search/report_employee_commission.html', '' ], - 'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ], - 'Unapplied Credits' => [ $fsurl.'search/report_cust_credit.html?unapplied=1', 'Unapplied credit report (by type and/or date range)' ], - 'Refund Report' => [ $fsurl.'search/report_cust_refund.html', 'Refund report (by type and/or date range)' ], - 'Unapplied Refunds' => [ $fsurl.'search/report_cust_refund.html?unapplied=1', 'Unapplied refund report (by type and/or date range)' ], - 'Package Costs Report' => [ $fsurl.'graph/report_cust_pkg_cost.html', 'Package setup and recurring costs graph' ], - 'Employee Audit Report' => [ $fsurl.'search/report_employee_audit.html', 'Employee audit report' ], + 'Sales' => [ \%report_sales, 'Sales reports', ], + 'Credits' => [ \%report_credits, 'Credit reports', ], + 'Refunds' => [ \%report_refunds, 'Refund reports', ], ); $report_financial{'A/R Aging'} = [ $fsurl.'search/report_receivables.html', 'Accounts Receivable Aging report' ]; $report_financial{'Prepaid Income'} = [ $fsurl.'search/report_prepaid_income.html', 'Prepaid income (unearned revenue) report' ]; @@ -346,36 +363,48 @@ if($curuser->access_right('Financial reports')) { } # else $report_financial contains nothing. +tie my %report_logs, 'Tie::IxHash'; + $report_logs{'System log'} = [ $fsurl.'search/log.html', 'View system events and debugging information.' ], + if $curuser->access_right('View system logs') + || $curuser->access_right('Configuration'); + $report_logs{'Outgoing messages'} = [ $fsurl.'search/cust_msg.html', 'View outgoing message log' ] + if $curuser->access_right('View email logs') + || $curuser->access_right('Configuration'); + tie my %report_menu, 'Tie::IxHash'; -$report_menu{'Prospects'} = [ \%report_prospects, 'Prospect reports' ] +$report_menu{'Prospects'} = [ \%report_prospects, 'Prospect reports' ] if $curuser->access_right('List prospects'); -$report_menu{'Quotations'} = [ \%report_quotations, 'Quotation reports' ] +$report_menu{'Quotations'} = [ \%report_quotations, 'Quotation reports' ] if $curuser->access_right('List quotations'); -$report_menu{'Customers'} = [ \%report_customers, 'Customer reports' ] +$report_menu{'Customers'} = [ \%report_customers, 'Customer reports' ] if $curuser->access_right('List customers'); -$report_menu{'Invoices'} = [ \%report_invoices, 'Invoice reports' ] +$report_menu{'Invoices'} = [ \%report_invoices, 'Invoice reports' ] if $curuser->access_right('List invoices'); -$report_menu{'Discounts'} = [ \%report_discounts, 'Discount reports' ] +$report_menu{'Discounts'} = [ \%report_discounts, 'Discount reports' ] if $curuser->access_right('Financial reports'); -$report_menu{'Payments'} = [ \%report_payments, 'Payment reports' ] +$report_menu{'Payments'} = [ \%report_payments, 'Payment reports' ] if $curuser->access_right('Financial reports'); -$report_menu{'Packages'} = [ \%report_packages, 'Package reports' ] +$report_menu{'Packages'} = [ \%report_packages, 'Package reports' ] if $curuser->access_right('List packages'); -$report_menu{'Services'} = [ \%report_services, 'Services reports' ] +$report_menu{'Services'} = [ \%report_services, 'Services reports' ] if $curuser->access_right('List services'); -$report_menu{'Inventory'} = [ \%report_inventory, 'Inventory reports' ] +$report_menu{'Inventory'} = [ \%report_inventory, 'Inventory reports' ] if $curuser->access_right('Configuration'); #XXX List inventory? -$report_menu{'Usage'} = [ \%report_rating, 'Usage reports' ] +$report_menu{'Usage'} = [ \%report_rating, 'Usage reports' ] if $curuser->access_right('List rating data'); -$report_menu{'Tickets'} = [ \%report_ticketing, 'Ticket reports' ] +$report_menu{'Tickets'} = [ \%report_ticketing, 'Ticket reports' ] if $conf->config('ticket_system') ;#&& FS::TicketSystem->access_right(\%session, 'Something'); +$report_menu{'Employees'} = [ \%report_employees, 'Employee reports' ] + if $curuser->access_right('Financial reports'); $report_menu{'Billing events'} = [ \%report_bill_event, 'Billing events' ] if $curuser->access_right('Billing event reports'); -$report_menu{'Financial'} = [ \%report_financial, 'Financial reports' ] +$report_menu{'Financial'} = [ \%report_financial, 'Financial reports' ] if $curuser->access_right('Financial reports') or $curuser->access_right('Receivables report'); -$report_menu{'SQL Query'} = [ $fsurl.'search/report_sql.html', 'SQL Query' ] +$report_menu{'Logs'} = [ \%report_logs, 'System and email logs' ] + if (keys %report_logs); # empty if the user has no rights to it +$report_menu{'SQL Query'} = [ $fsurl.'search/report_sql.html', 'SQL Query'] if $curuser->access_right('Raw SQL'); tie my %tools_importing, 'Tie::IxHash', @@ -440,8 +469,6 @@ $tools_menu{'Time Queue'} = [ $fsurl.'search/report_timeworked.html', 'View pen if $curuser->access_right('Time queue'); $tools_menu{'Attachments'} = [ $fsurl.'browse/cust_attachment.html', 'View customer attachments' ] if !$conf->config('disable_cust_attachment') and $curuser->access_right('View attachments') and $curuser->access_right('Browse attachments'); -$tools_menu{'Outgoing messages'} = [ $fsurl.'search/cust_msg.html', 'View outgoing message log' ] #shouldn't this be in the reports menu? - if $curuser->access_right('View email logs'); $tools_menu{'Importing'} = [ \%tools_importing, 'Import tools' ] if $curuser->access_right('Import'); $tools_menu{'Exporting'} = [ \%tools_exporting, 'Export tools' ] diff --git a/httemplate/elements/searchbar-address2.html b/httemplate/elements/searchbar-address2.html index d5e2b37d7..5f3b1f233 100644 --- a/httemplate/elements/searchbar-address2.html +++ b/httemplate/elements/searchbar-address2.html @@ -6,7 +6,7 @@ <BR> <INPUT TYPE="submit" VALUE="Search units" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px;padding-left:1px;padding-right:1px;margin-top:3px"> </FORM> - <% $menu_position eq 'left' ? '<BR>' : '' %> + <% $menu_position eq 'left' ? '<BR>' : '' |n %> % } diff --git a/httemplate/elements/searchbar-cust_bill.html b/httemplate/elements/searchbar-cust_bill.html index 7d24fbe9d..169315bf0 100644 --- a/httemplate/elements/searchbar-cust_bill.html +++ b/httemplate/elements/searchbar-cust_bill.html @@ -8,7 +8,7 @@ <BR> <INPUT TYPE="submit" VALUE="<% mt('Search invoices') |h %>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px;padding-left:1px;padding-right:1px;margin-top:3px"> </FORM> - <% $menu_position eq 'left' ? '<BR><BR>' : '' %> + <% $menu_position eq 'left' ? '<BR><BR>' : '' |n %> % } diff --git a/httemplate/elements/searchbar-cust_main.html b/httemplate/elements/searchbar-cust_main.html index 5d79aaa5e..9a98417c8 100644 --- a/httemplate/elements/searchbar-cust_main.html +++ b/httemplate/elements/searchbar-cust_main.html @@ -5,7 +5,7 @@ <A HREF="<%$fsurl%>search/report_cust_main.html" CLASS="fslink" STYLE="font-size: 11px"><% mt('Advanced') |h %></A> <INPUT TYPE="submit" VALUE="<% mt('Search customers') |h %>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px"> </FORM> - <% $menu_position eq 'left' ? '<BR>' : '' %> + <% $menu_position eq 'left' ? '<BR>' : '' |n %> % } diff --git a/httemplate/elements/searchbar-cust_svc.html b/httemplate/elements/searchbar-cust_svc.html index 766209d16..e4c2dc614 100644 --- a/httemplate/elements/searchbar-cust_svc.html +++ b/httemplate/elements/searchbar-cust_svc.html @@ -5,7 +5,7 @@ <A NOTYET="<%$fsurl%>search/svc_Smarter.html" STYLE="color: #cccccc; font-size:11px"><% mt('Advanced') |h %></A> <INPUT TYPE="submit" VALUE="<% mt('Search services') |h %>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px"> </FORM> - <% $menu_position eq 'left' ? '<BR>' : '' %> + <% $menu_position eq 'left' ? '<BR>' : '' |n %> % } diff --git a/httemplate/elements/searchbar-prospect.html b/httemplate/elements/searchbar-prospect.html index 68b90d4e3..ac363796e 100644 --- a/httemplate/elements/searchbar-prospect.html +++ b/httemplate/elements/searchbar-prospect.html @@ -5,7 +5,7 @@ <A HREF="<%$fsurl%>search/report_prospect_main.html" CLASS="fslink" STYLE="font-size: 11px">Adv</A> <INPUT TYPE="submit" VALUE="Search prospects" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px;padding-left:1px;padding-right:1px"> </FORM> - <% $menu_position eq 'left' ? '<BR>' : '' %> + <% $menu_position eq 'left' ? '<BR>' : '' |n %> % } diff --git a/httemplate/elements/searchbar-ticket.html b/httemplate/elements/searchbar-ticket.html index 30624f7d3..ae86dbcec 100644 --- a/httemplate/elements/searchbar-ticket.html +++ b/httemplate/elements/searchbar-ticket.html @@ -5,7 +5,7 @@ <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html?NewQuery=1" CLASS="fslink" STYLE="font-size:11px"><% mt('Advanced') |h %></A> <INPUT TYPE="submit" VALUE="<% mt('Search tickets') |h %>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px"> </FORM> - <% $menu_position eq 'left' ? '<BR>' : '' %> + <% $menu_position eq 'left' ? '<BR>' : '' |n %> % } diff --git a/httemplate/elements/select-did.html b/httemplate/elements/select-did.html index a69450c2a..6e205d8ff 100644 --- a/httemplate/elements/select-did.html +++ b/httemplate/elements/select-did.html @@ -16,8 +16,10 @@ Example: % if ( $export->option('restrict_selection') eq 'non-tollfree' % || !$export->option('restrict_selection') ) { <TABLE> - <TR> + +% if ( $export->get_dids_npa_select ) { + <TD VALIGN="top"> <% include('/elements/select-state.html', 'prefix' => 'phonenum_', #$field.'_', @@ -29,40 +31,73 @@ Example: %> <BR><FONT SIZE="-1">State</FONT> </TD> + + <TD VALIGN="top"> + <% include('/elements/select-areacode.html', + 'state_prefix' => 'phonenum_', #$field.'_', + 'svcpart' => $svcpart, + 'empty' => 'Select area code', + ) + %> + <BR><FONT SIZE="-1">Area code</FONT> + </TD> + + <TD VALIGN="top"> + <% include('/elements/select-exchange.html', + 'svcpart' => $svcpart, + 'empty' => 'Select exchange', + ) + %> + <BR><FONT SIZE="-1">City / Exchange</FONT> + </TD> + +% } else { + <TD VALIGN="top"> - <% include('/elements/select-areacode.html', - 'state_prefix' => 'phonenum_', #$field.'_', - 'svcpart' => $svcpart, - 'empty' => 'Select area code', - ) - %> - <BR><FONT SIZE="-1">Area code</FONT> - </TD> - <TD VALIGN="top"> - <% include('/elements/select-exchange.html', - 'svcpart' => $svcpart, - 'empty' => 'Select exchange', + <% include('/elements/select.html', + 'field' => 'phonenum_state', + 'id' => 'phonenum_state', + 'options' => [ '', @{ $export->get_dids } ], + 'labels' => { '' => 'Select province' }, + 'onchange' => 'phonenum_state_changed(this);', ) %> - <BR><FONT SIZE="-1">City / Exchange</FONT> + <BR><FONT SIZE="-1">Province</FONT> </TD> + + <TD VALIGN="top"> + <% include('/elements/select-region.html', + 'state_prefix' => 'phonenum_', #$field.'_', + 'svcpart' => $svcpart, + 'empty' => 'Select region', + ) + %> + <BR><FONT SIZE="-1">Region</FONT> + </TD> + +% } + <TD VALIGN="top"> <% include('/elements/select-phonenum.html', 'svcpart' => $svcpart, 'empty' => 'Select phone number', 'bulknum' => $bulknum, 'multiple' => $multiple, + 'region' => ! $export->get_dids_npa_select, ) %> <BR><FONT SIZE="-1">Phone number</FONT> </TD> - </TR> + </TR> </TABLE> % } -% if ( $export->option('restrict_selection') eq 'tollfree' -% || !$export->option('restrict_selection') ) { +% if ( ( $export->option('restrict_selection') eq 'tollfree' +% || !$export->option('restrict_selection') +% ) +% and $export->get_dids_can_tollfree +% ) { <font size="-1">Toll-free</font> <% include('/elements/select-phonenum.html', 'svcpart' => $svcpart, diff --git a/httemplate/elements/select-mib-popup.html b/httemplate/elements/select-mib-popup.html new file mode 100644 index 000000000..bd485ef65 --- /dev/null +++ b/httemplate/elements/select-mib-popup.html @@ -0,0 +1,186 @@ +<& /elements/header-popup.html &> +<DIV STYLE="visibility: hidden; position: absolute" ID="measurebox"></DIV> +<TABLE WIDTH="100%"> +<TR> + <TD WIDTH="30%" ALIGN="right">Module:</TD> + <TD><SELECT ID="select_module"></SELECT></TD> +</TR> +<TR> + <TD ALIGN="right">Object:</TD> + <TD><INPUT TYPE="text" NAME="path" ID="input_path" WIDTH="100%"></TD> +</TR> +<TR> + <TD COLSPAN=2> + <SELECT STYLE="width:100%" SIZE=12 ID="select_path"></SELECT> + </TD> +</TR> +<TR> + <TH ALIGN="center" COLSPAN=2 ID="mib_objectID"></TH> +</TR> +<TR> + <TD ALIGN="right">Module: </TD><TD ID="mib_moduleID"></TD> +</TR> +<TR> + <TD ALIGN="right">Data type: </TD><TD ID="mib_type"></TD> +</TR> +<TR> + <TH COLSPAN=2> + <BUTTON ID="submit_button" onclick="submit()" DISABLED=1>Continue</BUTTON> + </TH> +</TR> +</TABLE> +<& /elements/xmlhttp.html, + url => $p.'misc/xmlhttp-mib-browse.html', + subs => [qw( search get_module_list )], +&> +<SCRIPT TYPE="text/javascript"> + +var selected_mib; + +function show_info(state) { + document.getElementById('mib_objectID').style.display = + document.getElementById('mib_moduleID').style.display = + document.getElementById('mib_type').style.display = + state ? '' : 'none'; +} + +function clear_list() { + var select_path = document.getElementById('select_path'); + select_path.options.length = 0; +} + +var measurebox = document.getElementById('measurebox'); +function add_item(value) { + var select_path = document.getElementById('select_path'); + var input_path = document.getElementById('input_path'); + var opt = document.createElement('option'); + var v = value; + if ( v.match(/-$/) ) { + opt.className = 'leaf'; + v = v.substring(0, v.length - 1); + } + var optvalue = v; // may not be the name we display + // shorten these if they don't fit in the box + if ( v.length > 30 ) { // unless they're already really short + measurebox.innerHTML = v; + while ( measurebox.clientWidth > select_path.clientWidth - 10 + && v.match(/^\..*\./) ) { + v = v.replace(/^\.[^\.]+/, ''); + measurebox.innerHTML = v; + } + if ( optvalue != v ) { + v = '...' + v; + } + } + opt.value = optvalue; + opt.text = v; + opt.selected = (input_path.value == v); + select_path.add(opt, null); +} + +var timerID = 0; + +function populate(json_result) { + var result = JSON.parse(json_result); + clear_list(); + for (var x in result['choices']) { + opt = document.createElement('option'); + add_item(result['choices'][x]); + } + if ( result['objectID'] ) { + selected_mib = result; + show_info(true); + // show details on the selected node + document.getElementById('mib_objectID').innerHTML = result.objectID; + document.getElementById('mib_moduleID').innerHTML = result.moduleID; + document.getElementById('mib_type').innerHTML = result.type; + document.getElementById('submit_button').disabled = !result.type; + } else { + selected_mib = undefined; + show_info(false); + } +} + +function populate_modules(json_result) { + var result = JSON.parse(json_result); + var select_module = document.getElementById('select_module'); + var opt = document.createElement('option'); + opt.value = 'ANY'; + opt.text = '(any)'; + select_module.add(opt, null); + for (var x in result['modules']) { + opt = document.createElement('option'); + opt.value = opt.text = result['modules'][x]; + select_module.add(opt, null); + } +} + +function dispatch_search() { + // called from the interval timer + var search_string = document.getElementById('select_module').value + ':' + + document.getElementById('input_path').value; + + search(search_string, populate); +} + +function delayed_search() { + // onkeyup handler for the text input + // 500ms after the user stops typing, send the search request + if (timerID != 0) { + clearTimeout(timerID); + } + timerID = setTimeout(dispatch_search, 500); +} + +function handle_choose_object() { + // onchange handler for the selector + // when the user picks an option, set the text input to that, and then + // search for it as though it was entered + var input_path = document.getElementById('input_path'); + input_path.value = this.value; + dispatch_search(); +} + +function handle_choose_module() { + input_path.value = ''; // just to avoid confusion + delayed_search(); +} + +function submit() { +% if ( $callback ) { + <% $callback %>; + parent.nd(1); // close popup +% } else { + alert(document.getElementById('input_path').value); +% } +} + +var input_path = document.getElementById('input_path'); +input_path.onkeyup = delayed_search; +var select_path = document.getElementById('select_path'); +select_path.onchange = handle_choose_object; +var select_module = document.getElementById('select_module'); +select_module.onchange = handle_choose_module; +% if ( $cgi->param('curr_value') ) { +input_path.value = <% $cgi->param('curr_value') |js_string %>; +% } +dispatch_search(); +get_module_list('', populate_modules); + +</SCRIPT> +<& /elements/footer.html &> +<%init> +my $callback = 'alert("(no callback defined)" + selected_mib.stringify)'; +$cgi->param('callback') =~ /^(\w+)$/; +if ( $1 ) { + # construct the JS function call expresssion + $callback = 'window.parent.' . $1 . '(selected_mib'; + foreach ($cgi->param('arg')) { + # pass-through arguments + /^(\w+)$/ or next; + $callback .= ",'$1'"; + } + $callback .= ')'; +} + +</%init> diff --git a/httemplate/elements/select-phonenum.html b/httemplate/elements/select-phonenum.html index d555bf4b6..18abe3dea 100644 --- a/httemplate/elements/select-phonenum.html +++ b/httemplate/elements/select-phonenum.html @@ -12,7 +12,7 @@ what.options[length] = optionName; } - function <% $opt{'prefix'} %>exchange_changed(what, callback) { + function <% $opt{'prefix'} %><% $previous %>_changed(what, callback) { what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled'; what.form.<% $opt{'prefix'} %>phonenum.style.display = 'none'; @@ -21,7 +21,7 @@ var phonenumerror = document.getElementById('<% $opt{'prefix'} %>phonenumerror'); phonenumerror.style.display = 'none'; - exchange = what.options[what.selectedIndex].value; + var thing = "<% $previous eq 'region' ? '_REGION ' : '' %>" + what.options[what.selectedIndex].value; function <% $opt{'prefix'} %>update_phonenums(phonenums) { @@ -84,7 +84,7 @@ } // go get the new phonenums - <% $opt{'prefix'} %>get_phonenums( exchange, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_phonenums ); + <% $opt{'prefix'} %>get_phonenums( thing, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_phonenums ); } @@ -126,7 +126,7 @@ % unless ( $opt{'tollfree'} ) { <DIV ID="phonenumwait" STYLE="display:none"><IMG SRC="<%$fsurl%>images/wait-orange.gif"> <B>Finding phone numbers</B></DIV> -<DIV ID="phonenumerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different city/exchange</B></DIV> +<DIV ID="phonenumerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different <% $opt{'region'} ? 'region' : 'city/exchange' %></B></DIV> % } <SELECT <% $opt{multiple} ? 'MULTIPLE SIZE=25' : '' %> @@ -146,4 +146,6 @@ my %opt = @_; $opt{disabled} = 'disabled' unless exists $opt{disabled}; +my $previous = $opt{'region'} ? 'region' : 'exchange'; + </%init> diff --git a/httemplate/elements/select-region.html b/httemplate/elements/select-region.html new file mode 100644 index 000000000..9823290db --- /dev/null +++ b/httemplate/elements/select-region.html @@ -0,0 +1,88 @@ +<% include('/elements/xmlhttp.html', + 'url' => $p.'misc/regions.cgi', + 'subs' => [ $opt{'prefix'}. 'get_regions' ], + ) +%> + +<SCRIPT TYPE="text/javascript"> + + function opt(what,value,text) { + var optionName = new Option(text, value, false, false); + var length = what.length; + what.options[length] = optionName; + } + + function <% $opt{'state_prefix'} %>state_changed(what, callback) { + + what.form.<% $opt{'prefix'} %>region.disabled = 'disabled'; + what.form.<% $opt{'prefix'} %>region.style.display = 'none'; + var regionwait = document.getElementById('<% $opt{'prefix'} %>regionwait'); + regionwait.style.display = ''; + var regionerror = document.getElementById('<% $opt{'prefix'} %>regionerror'); + regionerror.style.display = 'none'; + + what.form.<% $opt{'prefix'} %>phonenum.disabled = 'disabled'; + + state = what.options[what.selectedIndex].value; + + function <% $opt{'prefix'} %>update_regions(regions) { + + // blank the current region + for ( var i = what.form.<% $opt{'prefix'} %>region.length; i >= 0; i-- ) + what.form.<% $opt{'prefix'} %>region.options[i] = null; + // blank the current phonenum too + for ( var i = what.form.<% $opt{'prefix'} %>phonenum.length; i >= 0; i-- ) + what.form.<% $opt{'prefix'} %>phonenum.options[i] = null; + if ( what.form.<% $opt{'prefix'} %>phonenum.type != 'select-multiple' ) { + opt(what.form.<% $opt{'prefix'} %>phonenum, '', 'Select phone number'); + } + +% if ($opt{empty}) { + opt(what.form.<% $opt{'prefix'} %>region, '', '<% $opt{empty} %>'); +% } + + // add the new regions + var regionArray = eval('(' + regions + ')' ); + for ( var s = 0; s < regionArray.length; s++ ) { + var regionLabel = regionArray[s]; + if ( regionLabel == "" ) + regionLabel = '(n/a)'; + opt(what.form.<% $opt{'prefix'} %>region, regionArray[s], regionLabel); + } + + regionwait.style.display = 'none'; + if ( regionArray.length >= 1 ) { + what.form.<% $opt{'prefix'} %>region.disabled = ''; + what.form.<% $opt{'prefix'} %>region.style.display = ''; + } else { + var regionerror = document.getElementById('<% $opt{'prefix'} %>regionerror'); + regionerror.style.display = ''; + } + + //run the callback + if ( callback != null ) + callback(); + } + + // go get the new regions + <% $opt{'prefix'} %>get_regions( state, <% $opt{'svcpart'} %>, <% $opt{'prefix'} %>update_regions ); + + } + +</SCRIPT> + +<DIV ID="<% $opt{'prefix'} %>regionwait" STYLE="display:none"><IMG SRC="<%$fsurl%>images/wait-orange.gif"> <B>Finding regions</B></DIV> + +<DIV ID="<% $opt{'prefix'} %>regionerror" STYLE="display:none"><IMG SRC="<%$fsurl%>images/cross.png"> <B>Select a different state</B></DIV> + +<SELECT NAME="<% $opt{'prefix'} %>region" onChange="<% $opt{'prefix'} %>region_changed(this); <% $opt{'onchange'} %>" <% $opt{'disabled'} %>> + <OPTION VALUE="">Select region</OPTION> +</SELECT> + +<%init> + +my %opt = @_; + +$opt{disabled} = 'disabled' unless exists $opt{disabled}; + +</%init> diff --git a/httemplate/elements/select-terms.html b/httemplate/elements/select-terms.html index d63c49219..a66aa29ae 100644 --- a/httemplate/elements/select-terms.html +++ b/httemplate/elements/select-terms.html @@ -33,7 +33,7 @@ my $empty_label = my $empty_value = $opt{'empty_value'} || ''; my @terms = ( emt('Payable upon receipt'), - ( map "Net $_", 0, 3, 9, 10, 15, 20, 30, 45, 60, 90 ), + ( map "Net $_", 0, 3, 9, 10, 15, 18, 20, 30, 45, 60, 90 ), ); my @pre_options = $opt{pre_options} ? @{ $opt{pre_options} } : (); diff --git a/httemplate/elements/standardize_locations.js b/httemplate/elements/standardize_locations.js index d9c1df7e6..15c5761a0 100644 --- a/httemplate/elements/standardize_locations.js +++ b/httemplate/elements/standardize_locations.js @@ -1,3 +1,9 @@ +function status_message(text, caption) { + text = '<P STYLE="position:absolute; top:50%; margin-top:-1em; width:100%; text-align:center"><B><FONT SIZE="+1">' + text + '</FONT></B></P>'; + caption = caption || 'Please wait...'; + overlib(text, WIDTH, 444, HEIGHT, 168, CAPTION, caption, STICKY, AUTOSTATUSCAP, CLOSECLICK, MIDX, 0, MIDY, 0); +} + function form_address_info() { var cf = document.<% $formname %>; @@ -87,8 +93,7 @@ function standardize_locations() { % if ( $conf->config('address_standardize_method') ) { if ( changed ) { - var startup_msg = '<P STYLE="position:absolute; top:50%; margin-top:-1em; width:100%; text-align:center"><B><FONT SIZE="+1">Verifying address...</FONT></B></P>'; - overlib(startup_msg, WIDTH, 444, HEIGHT, 168, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSECLICK, MIDX, 0, MIDY, 0); + status_message('Verifying address...'); address_standardize(JSON.stringify(address_info), confirm_standardize); } else { @@ -116,8 +121,14 @@ function confirm_standardize(arg) { replace_address(); // with the contents of returned['new'] - } - else { + } else if ( returned['all_same'] ) { + + // then all entered address fields are correct + // but we still need to set the lat/long fields and addr_clean + status_message('Verified'); + replace_address(); + + } else { var querystring = encodeURIComponent( JSON.stringify(returned) ); // confirmation popup: knows to call replace_address(), diff --git a/httemplate/elements/xmlhttp.html b/httemplate/elements/xmlhttp.html index ac6f9916e..a9e65c790 100644 --- a/httemplate/elements/xmlhttp.html +++ b/httemplate/elements/xmlhttp.html @@ -14,14 +14,15 @@ Example: ); </%doc> -<% include( '/elements/rs_init_object.html' ) %> +<& /elements/rs_init_object.html &> +<& /elements/init_overlib.html &> <SCRIPT TYPE="text/javascript"> % foreach my $func ( @{$opt{'subs'}} ) { % % my $furl = $url; % $furl =~ s/\"/\\\\\"/; #javascript escape -% +%#" % @@ -66,15 +67,26 @@ Example: } else { var data = xmlhttp.responseText; //alert('received response: ' + data); - a[a.length-1](data); if ( data.indexOf("<b>System error</b>") > -1 ) { - var w; - if ( w = window.open("about:blank") ) { - w.document.write(data); - } else { - // popup blocking? should use an overlib popup instead - alert("Error popup disabled; try disabling popup blocking to see"); - } + // trim this a little + var end = data.indexOf('<a href="#raw">') - 1; + data = data.substring(0, end); + + overlib(data, + WIDTH, 480, MIDX, 0, MIDY, 0, + CAPTION, 'Error', STICKY, AUTOSTATUSCAP, DRAGGABLE, + CLOSECLICK, BGCOLOR, '#f00', CGCOLOR, '#f00' + ); + //var w; + //if ( w = window.open("about:blank") ) { + // w.document.write(data); + //} else { + // // popup blocking? should use an overlib popup instead + // alert("Error popup disabled; try disabling popup blocking to see"); + //} + } else { + // invoke the callback + a[a.length-1](data); } } } |