2013-11-26 13:45:07 +01:00
@ extends ( 'header' )
2013-12-08 14:32:49 +01:00
@ section ( 'head' )
@ parent
< script type = " text/javascript " src = " { { asset('js/pdf_viewer.js') }} " ></ script >
< script type = " text/javascript " src = " { { asset('js/compatibility.js') }} " ></ script >
@ stop
2013-11-26 13:45:07 +01:00
@ section ( 'content' )
2013-12-07 19:45:00 +01:00
2013-11-26 13:45:07 +01:00
< p >& nbsp ; </ p >
2013-11-26 22:45:10 +01:00
{{ Former :: open ( $url ) -> method ( $method ) -> addClass ( 'main_form' ) -> rules ( array (
2013-12-08 14:32:49 +01:00
'client' => 'required' ,
2013-12-10 23:10:43 +01:00
'product_key' => 'max:14' ,
2013-11-26 22:45:10 +01:00
)); }}
2013-11-26 13:45:07 +01:00
2013-11-26 22:45:10 +01:00
<!-- < h3 > {{ $title }} Invoice </ h3 > -->
2013-11-26 13:45:07 +01:00
2013-11-26 22:45:10 +01:00
@ if ( $invoice )
{{ Former :: populate ( $invoice ); }}
2013-12-05 21:25:20 +01:00
{{ Former :: populateField ( 'id' , $invoice -> public_id ); }}
2013-12-07 21:33:07 +01:00
{{ Former :: populateField ( 'invoice_date' , Utils :: fromSqlDate ( $invoice -> invoice_date )); }}
{{ Former :: populateField ( 'due_date' , Utils :: fromSqlDate ( $invoice -> due_date )); }}
2013-12-09 10:38:49 +01:00
{{ Former :: populateField ( 'start_date' , Utils :: fromSqlDate ( $invoice -> start_date )); }}
2013-12-10 23:10:43 +01:00
{{ Former :: populateField ( 'end_date' , Utils :: fromSqlDate ( $invoice -> end_date )); }}
2013-11-26 22:45:10 +01:00
@ else
2013-12-01 13:22:08 +01:00
{{ Former :: populateField ( 'invoice_number' , $invoiceNumber ) }}
2013-11-28 13:15:34 +01:00
{{ Former :: populateField ( 'invoice_date' , date ( 'm/d/Y' )) }}
2013-12-11 12:11:59 +01:00
{{ Former :: populateField ( 'start_date' , date ( 'm/d/Y' )) }}
2013-12-10 23:10:43 +01:00
{{ Former :: populateField ( 'frequency' , FREQUENCY_MONTHLY ) }}
2013-11-26 22:45:10 +01:00
@ endif
2013-12-09 10:38:49 +01:00
< div class = " row " style = " min-height:195px " >
2013-12-11 21:33:44 +01:00
< div class = " col-md-7 " id = " col_1 " >
2013-12-07 19:45:00 +01:00
{{ Former :: select ( 'client' ) -> addOption ( '' , '' ) -> fromQuery ( $clients , 'name' , 'public_id' ) -> select ( $client ? $client -> public_id : '' ) -> addGroupClass ( 'client_select' )
2013-12-05 21:25:20 +01:00
-> help ( '<a style="cursor:pointer" data-toggle="modal" id="modalLink" onclick="showCreateNew()">Create new client</a>' ) }}
2013-12-11 21:33:44 +01:00
{{ Former :: text ( 'discount' ) -> data_bind ( " value: discount, valueUpdate: 'afterkeydown' " ) }}
2013-12-09 10:38:49 +01:00
{{ Former :: textarea ( 'notes' ) }}
2013-12-11 21:33:44 +01:00
2013-11-26 22:45:10 +01:00
</ div >
2013-12-11 21:33:44 +01:00
< div class = " col-md-4 " id = " col_2 " >
2013-12-10 23:10:43 +01:00
< div id = " recurring_checkbox " >
2013-12-11 21:33:44 +01:00
{{ Former :: checkbox ( 'recurring' ) -> text ( 'Enable | <a href="#">Learn more</a>' ) -> onchange ( 'toggleRecurring()' )
2013-12-10 23:10:43 +01:00
-> inlineHelp ( $invoice && $invoice -> last_sent_date ? 'Last invoice sent ' . Utils :: timestampToDateString ( $invoice -> last_sent_date ) : '' ) }}
</ div >
< div id = " recurring_off " >
{{ Former :: text ( 'invoice_number' ) -> label ( 'Invoice #' ) }}
2013-12-11 21:33:44 +01:00
{{ Former :: text ( 'po_number' ) -> label ( 'PO number' ) }}
2013-12-10 23:10:43 +01:00
{{ Former :: text ( 'invoice_date' ) }}
{{ Former :: text ( 'due_date' ) }}
2013-12-09 10:38:49 +01:00
2013-12-11 21:33:44 +01:00
2013-12-10 23:10:43 +01:00
{{ -- Former :: text ( 'invoice_date' ) -> label ( 'Invoice Date' ) -> data_date_format ( 'yyyy-mm-dd' ) -- }}
</ div >
< div id = " recurring_on " style = " display:none " >
{{ Former :: select ( 'frequency' ) -> label ( 'How often' ) -> options ( $frequencies ) -> onchange ( 'updateRecurringStats()' ) }}
{{ Former :: text ( 'start_date' ) -> onchange ( 'updateRecurringStats()' ) }}
{{ Former :: text ( 'end_date' ) -> onchange ( 'updateRecurringStats()' ) }}
</ div >
2013-12-11 21:33:44 +01:00
2013-12-09 10:38:49 +01:00
</ div >
2013-12-10 23:10:43 +01:00
< div class = " col-md-3 " id = " col_3 " style = " display:none " >
2013-12-11 21:33:44 +01:00
2013-11-26 22:45:10 +01:00
</ div >
</ div >
2013-11-26 13:45:07 +01:00
2013-11-26 22:45:10 +01:00
< p >& nbsp ; </ p >
2013-11-26 13:45:07 +01:00
2013-11-28 13:15:34 +01:00
{{ Former :: hidden ( 'items' ) -> data_bind ( " value: ko.toJSON(items) " ) }}
2013-11-27 08:38:37 +01:00
< table class = " table invoice-table " style = " margin-bottom: 0px !important " >
2013-11-26 22:45:10 +01:00
< thead >
< tr >
< th class = " hide-border " ></ th >
< th > Item </ th >
< th > Description </ th >
2013-12-11 21:33:44 +01:00
< th > Rate </ th >
< th > Units </ th >
2013-11-26 22:45:10 +01:00
< th > Line & nbsp ; Total </ th >
< th class = " hide-border " ></ th >
</ tr >
</ thead >
< tbody data - bind = " sortable: { data: items, afterMove: onDragged } " >
< tr data - bind = " event: { mouseover: showActions, mouseout: hideActions } " class = " sortable-row " >
2013-12-08 14:32:49 +01:00
< td style = " width:20px; " class = " hide-border td-icon " >
< i data - bind = " visible: actionsVisible() && $parent .items().length > 1 " class = " fa fa-sort " ></ i >
2013-11-26 22:45:10 +01:00
</ td >
2013-12-01 13:22:08 +01:00
< td style = " width:120px " >
{{ Former :: text ( 'product_key' ) -> useDatalist ( Product :: getProductKeys ( $products ), 'key' ) -> onkeyup ( 'onChange()' )
2013-11-28 13:15:34 +01:00
-> raw () -> data_bind ( " value: product_key, valueUpdate: 'afterkeydown' " ) -> addClass ( 'datalist' ) }}
2013-11-26 22:45:10 +01:00
</ td >
< td style = " width:300px " >
2013-12-01 13:22:08 +01:00
< textarea onkeyup = " checkWordWrap(event) " data - bind = " value: notes, valueUpdate: 'afterkeydown' " rows = " 1 " cols = " 60 " style = " resize: none; " class = " form-control " onchange = " refreshPDF() " ></ textarea >
2013-11-26 22:45:10 +01:00
</ td >
< td style = " width:100px " >
2013-12-01 13:22:08 +01:00
< input onkeyup = " onChange() " data - bind = " value: cost, valueUpdate: 'afterkeydown' " style = " text-align: right " class = " form-control " onchange = " refreshPDF() " //>
2013-11-26 22:45:10 +01:00
</ td >
< td style = " width:80px " >
2013-12-01 13:22:08 +01:00
< input onkeyup = " onChange() " data - bind = " value: qty, valueUpdate: 'afterkeydown' " style = " text-align: right " class = " form-control " onchange = " refreshPDF() " //>
2013-11-26 22:45:10 +01:00
</ td >
<!--
< td style = " width:100px " >
< input data - bind = " value: tax, valueUpdate: 'afterkeydown' " />
</ td >
-->
2013-12-07 19:45:00 +01:00
< td style = " width:100px;text-align: right;padding-top:9px !important " >
2013-11-26 22:45:10 +01:00
< span data - bind = " text: total " ></ span >
</ td >
2013-12-08 14:32:49 +01:00
< td style = " width:20px; cursor:pointer " class = " hide-border td-icon " >
2013-11-26 22:45:10 +01:00
& nbsp ; < i data - bind = " click: $parent .removeItem, visible: actionsVisible() && $parent .items().length > 1 " class = " fa fa-minus-circle " title = " Remove item " />
</ td >
</ tr >
</ tbody >
< tfoot >
2013-12-01 21:58:25 +01:00
< tr >
< td class = " hide-border " ></ td >
< td colspan = " 2 " />
2013-11-26 22:45:10 +01:00
< td colspan = " 2 " > Subtotal </ td >
< td style = " text-align: right " >< span data - bind = " text: subtotal " /></ td >
</ tr >
2013-12-01 21:58:25 +01:00
< tr >
< td class = " hide-border " ></ td >
< td colspan = " 2 " class = " hide-border " />
< td colspan = " 2 " > Paid to Date </ td >
< td style = " text-align: right " ></ td >
</ tr >
2013-11-26 22:45:10 +01:00
< tr data - bind = " visible: discount() > 0 " >
2013-12-01 21:58:25 +01:00
< td class = " hide-border " ></ td >
< td colspan = " 2 " class = " hide-border " />
2013-11-26 22:45:10 +01:00
< td colspan = " 2 " > Discount </ td >
< td style = " text-align: right " >< span data - bind = " text: discounted " /></ td >
</ tr >
< tr >
2013-11-28 13:15:34 +01:00
< td class = " hide-border " ></ td >
2013-12-01 21:58:25 +01:00
< td colspan = " 2 " class = " hide-border " />
2013-12-11 21:33:44 +01:00
< td colspan = " 2 " >< b > Balance Due </ b ></ td >
2013-11-26 22:45:10 +01:00
< td style = " text-align: right " >< span data - bind = " text: total " /></ td >
</ tr >
</ tfoot >
</ table >
2013-11-26 13:45:07 +01:00
2013-11-26 22:45:10 +01:00
< p >& nbsp ; </ p >
< div class = " form-actions " >
2013-12-03 18:32:33 +01:00
2013-12-07 19:45:00 +01:00
< div style = " display:none " >
{{ Former :: text ( 'action' ) }}
@ if ( $invoice )
2013-12-05 21:25:20 +01:00
{{ Former :: text ( 'id' ) }}
2013-12-07 19:45:00 +01:00
@ endif
</ div >
2013-12-11 21:33:44 +01:00
{{ Button :: normal ( 'Download PDF' , array ( 'onclick' => 'onDownloadClick()' )) }}
2013-12-07 19:45:00 +01:00
@ if ( $invoice )
2013-12-11 21:33:44 +01:00
{{ DropdownButton :: primary ( 'Save Invoice' ,
2013-12-03 18:32:33 +01:00
Navigation :: links (
array (
2013-12-11 21:33:44 +01:00
array ( 'Save Invoice' , " javascript:onSaveClick() " ),
array ( 'Clone Invoice' , " javascript:onCloneClick() " ),
2013-12-03 18:32:33 +01:00
array ( Navigation :: DIVIDER ),
array ( 'Archive Invoice' , " javascript:onArchiveClick() " ),
array ( 'Delete Invoice' , " javascript:onDeleteClick() " ),
)
)
, array ( 'id' => 'actionDropDown' , 'style' => 'text-align:left' )) -> split (); }}
@ else
2013-12-11 21:33:44 +01:00
{{ Button :: primary_submit ( 'Save Invoice' ) }}
2013-12-03 18:32:33 +01:00
@ endif
2013-12-10 23:10:43 +01:00
{{ Button :: primary ( 'Send Email' , array ( 'id' => 'email_button' , 'onclick' => 'onEmailClick()' )) }}
2013-11-26 13:45:07 +01:00
</ div >
2013-11-26 22:45:10 +01:00
< p >& nbsp ; </ p >
<!-- < textarea rows = " 20 " cols = " 120 " id = " pdfText " onkeyup = " runCode() " ></ textarea > -->
2013-11-27 08:38:37 +01:00
<!-- < iframe frameborder = " 1 " width = " 100% " height = " 600 " style = " display:block;margin: 0 auto " ></ iframe > -->
2013-12-11 21:33:44 +01:00
< iframe id = " theIFrame " frameborder = " 1 " width = " 100% " height = " 500 " ></ iframe >
< canvas id = " theCanvas " style = " display:none;width:100%;border:solid 1px #CCCCCC; " ></ canvas >
2013-11-26 13:45:07 +01:00
< div class = " modal fade " id = " myModal " tabindex = " -1 " role = " dialog " aria - labelledby = " myModalLabel " aria - hidden = " true " >
2013-12-05 21:25:20 +01:00
< div class = " modal-dialog " style = " min-width:1000px " >
2013-11-26 13:45:07 +01:00
< div class = " modal-content " >
< div class = " modal-header " >
< button type = " button " class = " close " data - dismiss = " modal " aria - hidden = " true " >& times ; </ button >
< h4 class = " modal-title " id = " myModalLabel " > New Client </ h4 >
</ div >
2013-12-05 21:25:20 +01:00
< div class = " row " style = " padding-left:16px;padding-right:16px " onkeypress = " preventFormSubmit(event) " >
< div class = " col-md-6 " >
{{ Former :: legend ( 'Organization' ) }}
{{ Former :: text ( 'name' ) }}
{{ Former :: text ( 'work_phone' ) -> label ( 'Phone' ) }}
{{ Former :: legend ( 'Contact' ) }}
{{ Former :: text ( 'first_name' ) }}
{{ Former :: text ( 'last_name' ) }}
{{ Former :: text ( 'email' ) }}
{{ Former :: text ( 'phone' ) }}
</ div >
< div class = " col-md-6 " >
{{ Former :: legend ( 'Address' ) }}
{{ Former :: text ( 'address1' ) -> label ( 'Street' ) }}
{{ Former :: text ( 'address2' ) -> label ( 'Apt/Floor' ) }}
{{ Former :: text ( 'city' ) }}
{{ Former :: text ( 'state' ) }}
{{ Former :: text ( 'postal_code' ) }}
2013-12-07 19:45:00 +01:00
{{ Former :: select ( 'country_id' ) -> addOption ( '' , '' ) -> label ( 'Country' ) -> addGroupClass ( 'country_select' )
2013-12-05 21:25:20 +01:00
-> fromQuery ( $countries , 'name' , 'id' ) -> select ( $client ? $client -> country_id : '' ) }}
</ div >
</ div >
<!--
2013-11-26 13:45:07 +01:00
< div class = " modal-body " style = " min-height:80px " >
2013-11-28 13:15:34 +01:00
< div class = " form-group " >
2013-11-26 13:45:07 +01:00
< label for = " name " class = " control-label col-lg-2 col-sm-4 " > Name < sup >*</ sup ></ label >
< div class = " col-lg-10 col-sm-8 " >
< input class = " form-control " id = " client_name " type = " text " name = " client_name " onkeypress = " nameKeyPress(event) " >
< span class = " help-block " id = " nameHelp " style = " display: none " > Please provide a value </ span >< span >& nbsp ; </ span >
</ div >
</ div >
2013-11-28 13:15:34 +01:00
< div class = " form-group " >
2013-11-26 13:45:07 +01:00
< label for = " email " class = " control-label col-lg-2 col-sm-4 " > Email < sup >*</ sup ></ label >
< div class = " col-lg-10 col-sm-8 " >
< input class = " form-control " id = " client_email " type = " text " name = " client_email " onkeypress = " nameKeyPress(event) " >
< span class = " help-block " id = " emailHelp " style = " display: none " > Please provide a value </ span >< span >& nbsp ; </ span >
</ div >
</ div >
</ div >
2013-12-05 21:25:20 +01:00
-->
2013-11-26 13:45:07 +01:00
< div class = " modal-footer " >
2013-12-05 21:25:20 +01:00
< span class = " error-block " id = " nameError " style = " display:none;float:left " > Please provide a value for the name field .</ span >< span >& nbsp ; </ span >
< button type = " button " class = " btn btn-default " data - dismiss = " modal " > Cancel </ button >
< button type = " button " class = " btn btn-primary " onclick = " newClient() " > Done </ button >
2013-11-26 13:45:07 +01:00
</ div >
2013-12-05 21:25:20 +01:00
2013-11-26 13:45:07 +01:00
</ div >
</ div >
</ div >
{{ Former :: close () }}
< script type = " text/javascript " >
/*
function textarea_height ( TextArea , MaxHeight ) {
textarea = document . getElementById ( TextArea );
textareaRows = textarea . value . split ( " \n " );
if ( textareaRows [ 0 ] != " undefined " && textareaRows . length < MaxHeight ) counter = textareaRows . length ;
else if ( textareaRows . length >= MaxHeight ) counter = MaxHeight ;
else counter = 1 ;
textarea . rows = counter ;
}
*/
2013-11-27 08:38:37 +01:00
2013-11-26 13:45:07 +01:00
$ ( function () {
2013-12-11 21:33:44 +01:00
$ ( 'form' ) . change ( refreshPDF );
2013-12-05 21:25:20 +01:00
$ ( '#country_id' ) . combobox ();
2013-11-28 13:15:34 +01:00
$ ( '#invoice_date' ) . datepicker ({
2013-11-26 13:45:07 +01:00
autoclose : true ,
todayHighlight : true
});
2013-12-10 18:18:35 +01:00
$ ( '#due_date, #start_date, #end_date' ) . datepicker ({
2013-11-28 17:40:13 +01:00
autoclose : true ,
todayHighlight : true
});
2013-11-26 13:45:07 +01:00
var $input = $ ( 'select#client' );
$input . combobox ();
2013-12-08 14:32:49 +01:00
$ ( '.client_select input.form-control' ) . on ( 'change' , function ( e ) {
2013-12-11 21:33:44 +01:00
var clientId = parseInt ( $ ( 'input[name=client]' ) . val (), 10 );
$ ( '#modalLink' ) . text ( clientId ? 'Edit client details' : 'Create new client' );
if ( clientId > 0 ) {
loadClientDetails ( clientId );
2013-12-08 14:32:49 +01:00
}
2013-12-11 21:33:44 +01:00
}) . trigger ( 'change' );
2013-12-07 19:45:00 +01:00
//enableHoverClick($('.combobox-container input.form-control'), $('.combobox-container input[name=client]'), '{{ URL::to('clients') }}');
2013-11-26 13:45:07 +01:00
@ if ( $client )
2013-12-08 20:08:17 +01:00
$ ( '#invoice_number' ) . focus ();
2013-11-26 13:45:07 +01:00
@ else
2013-12-07 19:45:00 +01:00
//$('[name="client_combobox"]').focus();
2013-11-26 13:45:07 +01:00
@ endif
/*
$ ( '#myModal' ) . on ( 'hidden.bs.modal' , function () {
$ ( '#popup_client_name' ) . val ( '' );
})
*/
$ ( '#myModal' ) . on ( 'shown.bs.modal' , function () {
2013-12-05 21:25:20 +01:00
$ ( '#name' ) . focus ();
2013-11-26 13:45:07 +01:00
})
2013-11-28 13:15:34 +01:00
$ ( '#invoice_number' ) . change ( refreshPDF );
2013-11-26 13:45:07 +01:00
2013-12-03 18:32:33 +01:00
$ ( '#actionDropDown > button:first' ) . click ( function () {
2013-12-11 21:33:44 +01:00
onSaveClick ();
2013-12-03 18:32:33 +01:00
});
2013-12-10 23:10:43 +01:00
$ ( 'label.radio' ) . addClass ( 'radio-inline' );
2013-12-11 12:11:59 +01:00
@ if ( $invoice && $invoice -> isRecurring ())
2013-12-10 23:10:43 +01:00
$ ( '#recurring' ) . prop ( 'checked' , true );
@ elseif ( isset ( $invoice -> recurring_invoice_id ) && $invoice -> recurring_invoice_id )
2013-12-11 12:11:59 +01:00
$ ( '#recurring_checkbox > div > div' ) . html ( 'Created by a {{ link_to(' / invoices / '.$invoice->recurring_invoice_id, ' recurring invoice ') }}' ) . css ( 'padding-top' , '6px' );
2013-12-11 21:33:44 +01:00
@ elseif ( $invoice && $invoice -> isSent ())
$ ( '#recurring_checkbox' ) . hide ();
2013-12-10 23:10:43 +01:00
@ endif
2013-12-11 21:33:44 +01:00
toggleRecurring ();
2013-12-09 10:38:49 +01:00
2013-11-27 08:38:37 +01:00
applyComboboxListeners ();
refreshPDF ();
2013-11-26 13:45:07 +01:00
});
2013-12-11 21:33:44 +01:00
function loadClientDetails ( clientId ) {
var client = clientMap [ clientId ];
$ ( '#name' ) . val ( client . name );
$ ( '#work_phone' ) . val ( client . work_phone );
$ ( '#address1' ) . val ( client . address1 );
$ ( '#address2' ) . val ( client . address2 );
$ ( '#city' ) . val ( client . city );
$ ( '#state' ) . val ( client . state );
$ ( '#postal_code' ) . val ( client . postal_code );
$ ( '#country_id' ) . val ( client . country_id ) . combobox ( 'refresh' );
for ( var i = 0 ; i < client . contacts . length ; i ++ ) {
var contact = client . contacts [ i ];
if ( contact . is_primary ) {
$ ( '#first_name' ) . val ( contact . first_name );
$ ( '#last_name' ) . val ( contact . last_name );
$ ( '#email' ) . val ( contact . email );
$ ( '#phone' ) . val ( contact . phone );
}
}
}
function showCreateNew () {
if ( ! $ ( 'input[name=client]' ) . val ()) {
2013-12-05 21:25:20 +01:00
$ ( '#myModal input' ) . val ( '' );
$ ( '#myModal #country_id' ) . val ( '' );
$ ( '#nameError' ) . css ( " display " , " none " );
2013-12-11 21:33:44 +01:00
}
2013-12-05 21:25:20 +01:00
$ ( '#myModal' ) . modal ( 'show' );
}
2013-11-27 08:38:37 +01:00
function applyComboboxListeners () {
var value ;
$ ( '.datalist' ) . on ( 'focus' , function () {
value = $ ( this ) . val ();
}) . on ( 'blur' , function () {
if ( value != $ ( this ) . val ()) refreshPDF ();
2013-12-03 18:32:33 +01:00
}) . on ( 'input' , function () {
2013-11-27 08:38:37 +01:00
var key = $ ( this ) . val ();
for ( var i = 0 ; i < products . length ; i ++ ) {
var product = products [ i ];
2013-12-04 17:20:14 +01:00
if ( product . product_key == key ) {
2013-11-27 08:38:37 +01:00
var model = ko . dataFor ( this );
model . notes ( product . notes );
model . cost ( product . cost );
2013-11-28 13:15:34 +01:00
model . qty ( product . qty );
2013-11-27 08:38:37 +01:00
break ;
}
}
});
}
2013-11-26 13:45:07 +01:00
function runCode () {
var text = $ ( '#pdfText' ) . val ();
eval ( text );
}
function createInvoiceModel () {
var invoice = {
2013-11-28 13:15:34 +01:00
invoice_number : $ ( '#invoice_number' ) . val (),
invoice_date : $ ( '#invoice_date' ) . val (),
2013-12-11 21:33:44 +01:00
discount : parseFloat ( $ ( '#discount' ) . val ()),
po_number : $ ( '#po_number' ) . val (),
2013-12-01 21:58:25 +01:00
account : {
name : " { { $account->name }} " ,
address1 : " { { $account->address1 }} " ,
address2 : " { { $account->address2 }} " ,
city : " { { $account->city }} " ,
state : " { { $account->state }} " ,
postal_code : " { { $account->postal_code }} " ,
country : {
2013-12-02 13:22:29 +01:00
name : " { { $account->country ? $account->country ->name : '' }} "
2013-12-01 21:58:25 +01:00
}
},
2013-11-26 13:45:07 +01:00
@ if ( file_exists ( $account -> getLogoPath ()))
image : " { { HTML::image_data( $account->getLogoPath ()) }} " ,
imageWidth : {{ $account -> getLogoWidth () }},
imageHeight : {{ $account -> getLogoHeight () }},
@ endif
invoice_items : []
};
2013-12-11 21:33:44 +01:00
var client = {
name : $ ( '#name' ) . val (),
address1 : $ ( '#address1' ) . val (),
address2 : $ ( '#address2' ) . val (),
city : $ ( '#city' ) . val (),
state : $ ( '#state' ) . val (),
postal_code : $ ( '#postal_code' ) . val (),
country : {
name : $ ( '.country_select input[type=text]' ) . val ()
}
};
/*
var clientId = $ ( 'input[name=client]' ) . val ();
2013-12-07 19:45:00 +01:00
if ( clientId == '-1' ) {
var client = {
name : $ ( '#name' ) . val (),
address1 : $ ( '#address1' ) . val (),
address2 : $ ( '#address2' ) . val (),
city : $ ( '#city' ) . val (),
state : $ ( '#state' ) . val (),
postal_code : $ ( '#postal_code' ) . val (),
country : {
name : $ ( '.country_select input[type=text]' ) . val ()
}
};
} else if ( clientMap . hasOwnProperty ( clientId )) {
var client = clientMap [ clientId ];
}
2013-12-11 21:33:44 +01:00
*/
2013-12-07 19:45:00 +01:00
invoice . client = client ;
2013-11-26 13:45:07 +01:00
for ( var i = 0 ; i < model . items () . length ; i ++ ) {
var item = model . items ()[ i ];
invoice . invoice_items . push ({
product_key : item . product_key (),
notes : item . notes (),
cost : item . cost (),
qty : item . qty ()
});
}
return invoice ;
}
function refreshPDF () {
2013-12-07 19:45:00 +01:00
setTimeout ( function () {
_refreshPDF ();
}, 100 );
}
2013-12-08 14:32:49 +01:00
2013-12-07 19:45:00 +01:00
function _refreshPDF () {
2013-11-26 13:45:07 +01:00
var invoice = createInvoiceModel ();
2013-12-11 21:33:44 +01:00
var doc = generatePDF ( invoice );
/*
2013-12-08 14:32:49 +01:00
var string = doc . output ( 'dataurlstring' );
var pdfAsArray = convertDataURIToBinary ( string );
PDFJS . getDocument ( pdfAsArray ) . then ( function getPdfHelloWorld ( pdf ) {
pdf . getPage ( 1 ) . then ( function getPageHelloWorld ( page ) {
var scale = 1.5 ;
var viewport = page . getViewport ( scale );
2013-12-11 21:33:44 +01:00
var canvas = document . getElementById ( 'theCanvas' );
2013-12-08 14:32:49 +01:00
var context = canvas . getContext ( '2d' );
canvas . height = viewport . height ;
canvas . width = viewport . width ;
page . render ({ canvasContext : context , viewport : viewport });
});
2013-12-08 20:08:17 +01:00
});
2013-12-11 21:33:44 +01:00
*/
2013-12-08 14:32:49 +01:00
2013-12-11 21:33:44 +01:00
var string = doc . output ( 'datauristring' );
$ ( '#theIFrame' ) . attr ( 'src' , string );
2013-12-07 19:45:00 +01:00
}
2013-11-26 13:45:07 +01:00
function onDownloadClick () {
var invoice = createInvoiceModel ();
var doc = generatePDF ( invoice );
2013-12-08 20:08:17 +01:00
doc . save ( 'Invoice-' + $ ( '#invoice_number' ) . val () + '.pdf' );
2013-11-26 13:45:07 +01:00
}
function onEmailClick () {
if ( confirm ( 'Are you sure you want to email this invoice?' )) {
2013-12-03 18:32:33 +01:00
$ ( '#action' ) . val ( 'email' );
2013-11-26 13:45:07 +01:00
$ ( '.main_form' ) . submit ();
}
}
2013-12-11 21:33:44 +01:00
function onSaveClick () {
$ ( '.main_form' ) . submit ();
}
function onCloneClick () {
$ ( '#action' ) . val ( 'clone' );
$ ( '.main_form' ) . submit ();
}
2013-12-03 18:32:33 +01:00
function onArchiveClick () {
$ ( '#action' ) . val ( 'archive' );
$ ( '.main_form' ) . submit ();
}
function onDeleteClick () {
if ( confirm ( 'Are you sure you want to delete this invoice?' )) {
$ ( '#action' ) . val ( 'delete' );
$ ( '.main_form' ) . submit ();
}
}
2013-11-26 13:45:07 +01:00
function newClient () {
2013-12-05 21:25:20 +01:00
var name = $ ( '#name' ) . val ();
if ( ! name ) {
if ( ! name ) $ ( '#nameError' ) . css ( " display " , " inline " );
2013-11-26 13:45:07 +01:00
} else {
2013-12-08 14:32:49 +01:00
$ ( 'select#client' ) . combobox ( 'setSelected' );
2013-12-11 21:33:44 +01:00
if ( ! $ ( 'input[name=client]' ) . val ()) {
$ ( 'input[name=client]' ) . val ( '-1' );
}
2013-12-07 19:45:00 +01:00
$ ( '.client_select input.form-control' ) . val ( name );
2013-12-08 20:08:17 +01:00
$ ( '.client_select .combobox-container' ) . addClass ( 'combobox-selected' );
2013-11-26 13:45:07 +01:00
2013-12-05 21:25:20 +01:00
$ ( '#nameError' ) . css ( " display " , " none " );
$ ( '#modalLink' ) . text ( 'Edit client details' );
2013-11-26 13:45:07 +01:00
$ ( '#myModal' ) . modal ( 'hide' );
2013-12-08 20:08:17 +01:00
$ ( '.client_select input.form-control' ) . focus ();
2013-11-26 13:45:07 +01:00
refreshPDF ();
}
}
2013-12-05 21:25:20 +01:00
function preventFormSubmit ( event ) {
2013-11-26 13:45:07 +01:00
if ( event . keyCode === 13 ){
event . preventDefault ();
newClient ();
return false ;
}
}
function InvoiceModel () {
var self = this ;
self . discount = ko . observable ();
self . items = ko . observableArray ();
2013-11-28 13:15:34 +01:00
@ if ( isset ( $items ) && $items )
@ foreach ( $items as $item )
var item = new ItemModel ();
item . product_key ( " { { $item->product_key }} " );
item . notes ( '{{ str_replace("\n", "\\n", $item->notes) }}' );
item . cost ( " { { isset( $item->cost ) ? $item->cost : '' }} " );
item . qty ( " { { isset( $item->qty ) ? $item->qty : '' }} " );
self . items . push ( item );
@ endforeach
@ elseif ( $invoice )
2013-11-26 13:45:07 +01:00
self . discount ({{ $invoice -> discount }});
@ if ( count ( $invoice -> invoice_items ) > 0 )
@ foreach ( $invoice -> invoice_items as $item )
var item = new ItemModel ();
item . product_key ( " { { $item->product_key }} " );
2013-11-28 13:15:34 +01:00
item . notes ( '{{ str_replace("\n", "\\n", $item->notes) }}' );
2013-11-26 13:45:07 +01:00
item . cost ( " { { $item->cost }} " );
item . qty ( " { { $item->qty }} " );
self . items . push ( item );
@ endforeach
@ endif
2013-12-03 18:32:33 +01:00
@ endif
self . items . push ( new ItemModel ());
2013-11-26 13:45:07 +01:00
self . removeItem = function ( item ) {
self . items . remove ( item );
refreshPDF ();
}
self . addItem = function () {
self . items . push ( new ItemModel ());
2013-11-27 08:38:37 +01:00
applyComboboxListeners ();
2013-11-26 13:45:07 +01:00
}
this . rawSubtotal = ko . computed ( function () {
var total = 0 ;
for ( var p = 0 ; p < self . items () . length ; ++ p )
{
total += self . items ()[ p ] . rawTotal ();
}
return total ;
});
this . subtotal = ko . computed ( function () {
var total = self . rawSubtotal ();
return total > 0 ? formatMoney ( total ) : '' ;
});
this . discounted = ko . computed ( function () {
var total = self . rawSubtotal () * ( self . discount () / 100 );
return formatMoney ( total );
});
this . total = ko . computed ( function () {
var total = self . rawSubtotal ();
2013-12-11 21:33:44 +01:00
var discount = parseFloat ( self . discount ());
2013-11-26 13:45:07 +01:00
if ( discount > 0 ) {
total = total * (( 100 - discount ) / 100 );
}
return total > 0 ? formatMoney ( total ) : '' ;
});
self . onDragged = function ( item ) {
refreshPDF ();
}
}
function ItemModel () {
var self = this ;
this . product_key = ko . observable ( '' );
this . notes = ko . observable ( '' );
this . cost = ko . observable ();
this . qty = ko . observable ();
this . tax = ko . observable ();
this . actionsVisible = ko . observable ( false );
this . rawTotal = ko . computed ( function () {
var cost = parseFloat ( self . cost ());
2013-12-08 14:32:49 +01:00
var qty = parseFloat ( self . qty ());
2013-11-26 13:45:07 +01:00
var tax = parseFloat ( self . tax ());
var value = cost * qty ;
if ( self . tax () > 0 ) {
//value = value * ((100 - this.tax())/100);
}
return value ? value : '' ;
});
this . total = ko . computed ( function () {
var total = self . rawTotal ();
return total ? formatMoney ( total ) : '' ;
});
this . hideActions = function () {
this . actionsVisible ( false );
}
this . showActions = function () {
this . actionsVisible ( true );
}
2013-12-01 13:22:08 +01:00
this . isEmpty = function () {
return ! self . product_key () && ! self . notes () && ! self . cost () && ! self . qty () && ! self . tax ();
}
}
function checkWordWrap ( event )
{
var doc = new jsPDF ( 'p' , 'pt' );
doc . setFont ( 'Helvetica' , '' );
doc . setFontSize ( 10 );
var $textarea = $ ( event . target || event . srcElement );
var lines = $textarea . val () . split ( " \n " );
for ( var i = 0 ; i < lines . length ; i ++ ) {
var numLines = doc . splitTextToSize ( lines [ i ], 200 ) . length ;
if ( numLines <= 1 ) continue ;
var j = 0 ; space = lines [ i ] . length ;
while ( j ++ < lines [ i ] . length ) {
if ( lines [ i ] . charAt ( j ) === " " ) space = j ;
}
lines [ i + 1 ] = lines [ i ] . substring ( space + 1 ) + ( lines [ i + 1 ] || " " );
lines [ i ] = lines [ i ] . substring ( 0 , space );
}
var val = lines . slice ( 0 , 6 ) . join ( " \n " );
if ( val != $textarea . val ())
{
var model = ko . dataFor ( $textarea [ 0 ]);
model . notes ( val );
refreshPDF ();
}
$textarea . height ( val . split ( '\n' ) . length * 22 );
onChange ();
}
function onChange ()
{
var hasEmpty = false ;
for ( var i = 0 ; i < model . items () . length ; i ++ ) {
var item = model . items ()[ i ];
if ( item . isEmpty ()) {
hasEmpty = true ;
}
}
if ( ! hasEmpty ) {
model . addItem ();
}
2013-11-26 13:45:07 +01:00
}
2013-12-10 23:10:43 +01:00
function toggleRecurring ()
2013-12-09 10:38:49 +01:00
{
2013-12-10 23:10:43 +01:00
var enabled = $ ( '#recurring' ) . is ( ':checked' );
if ( enabled ) {
$ ( '#recurring_on' ) . show ();
$ ( '#recurring_off' ) . hide ();
$ ( '#email_button' ) . prop ( 'disabled' , true );
} else {
$ ( '#recurring_on' ) . hide ();
$ ( '#recurring_off' ) . show ();
$ ( '#email_button' ) . prop ( 'disabled' , false );
}
/*
2013-12-09 10:38:49 +01:00
$ ( '#col_1' ) . toggleClass ( 'col-md-6 col-md-5' );
$ ( '#col_2' ) . toggleClass ( 'col-md-5 col-md-3' );
if ( show ) {
setTimeout ( function () {
$ ( '#col_3' ) . show ();
}, 500 );
} else {
$ ( '#col_3' ) . hide ();
}
$ ( '#showRecurring,#hideRecurring' ) . toggle ();
if ( ! show ) {
$ ( '#how_often, #start_date, #end_date' ) . val ( '' )
}
2013-12-10 23:10:43 +01:00
*/
};
function updateRecurringStats ()
{
/*
var howOften = $ ( '#how_often' ) . val ();
var startDate = $ ( '#start_date' ) . val ();
var endDate = $ ( '#end_date' ) . val ();
console . log ( " %s %s %s " , howOften , startDate , endDate );
var str = " Send " ;
if ( ! endDate ) {
str += " an unlimited number of " ;
} else {
str += " " ;
}
str += " emails " ;
$ ( '#stats' ) . html ( str );
*/
}
2013-12-09 10:38:49 +01:00
2013-11-27 08:38:37 +01:00
var products = {{ $products }};
2013-12-07 19:45:00 +01:00
var clients = {{ $clients }};
var clientMap = {};
for ( var i = 0 ; i < clients . length ; i ++ ) {
var client = clients [ i ];
clientMap [ client . public_id ] = client ;
}
2013-11-27 08:38:37 +01:00
2013-11-26 13:45:07 +01:00
window . model = new InvoiceModel ();
ko . applyBindings ( model );
2013-11-27 08:38:37 +01:00
2013-11-26 13:45:07 +01:00
</ script >
@ stop