1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-18 00:53:10 +01:00

Floats Handling and PDF.js support

This commit is contained in:
Hillel Coren 2013-12-08 15:32:49 +02:00
parent b7f09685d0
commit ccd7a9f3a7
15 changed files with 47814 additions and 45 deletions

View File

@ -370,7 +370,7 @@ class InvoiceController extends \BaseController {
$item->qty = 0; $item->qty = 0;
} }
$total += intval($item->qty) * floatval($item->cost); $total += floatval($item->qty) * floatval($item->cost);
} }
if ($action == 'email' && $invoice->invoice_status_id == INVOICE_STATUS_DRAFT) if ($action == 'email' && $invoice->invoice_status_id == INVOICE_STATUS_DRAFT)
@ -415,7 +415,7 @@ class InvoiceController extends \BaseController {
$invoiceItem->product_key = trim($item->product_key); $invoiceItem->product_key = trim($item->product_key);
$invoiceItem->notes = trim($item->notes); $invoiceItem->notes = trim($item->notes);
$invoiceItem->cost = floatval($item->cost); $invoiceItem->cost = floatval($item->cost);
$invoiceItem->qty = intval($item->qty); $invoiceItem->qty = floatval($item->qty);
$invoice->invoice_items()->save($invoiceItem); $invoice->invoice_items()->save($invoiceItem);
} }

View File

@ -36,7 +36,7 @@ class PaymentController extends \BaseController
$table->addColumn('client_name', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); }); $table->addColumn('client_name', function($model) { return link_to('clients/' . $model->client_public_id, $model->client_name); });
} }
return $table->addColumn('invoice_number', function($model) { return $model->invoice_public_id ? link_to('invoices/' . $model->invoice_public_id . '/edit', $model->invoice_invoice_number) : ''; }) return $table->addColumn('invoice_number', function($model) { return $model->invoice_public_id ? link_to('invoices/' . $model->invoice_public_id . '/edit', $model->invoice_number) : ''; })
->addColumn('amount', function($model) { return '$' . $model->amount; }) ->addColumn('amount', function($model) { return '$' . $model->amount; })
->addColumn('payment_date', function($model) { return Utils::timestampToDateString($model->payment_date); }) ->addColumn('payment_date', function($model) { return Utils::timestampToDateString($model->payment_date); })
->addColumn('dropdown', function($model) ->addColumn('dropdown', function($model)

View File

@ -256,7 +256,7 @@ class ConfideSetupUsersTable extends Migration {
$t->string('product_key'); $t->string('product_key');
$t->string('notes'); $t->string('notes');
$t->decimal('cost', 10, 2); $t->decimal('cost', 10, 2);
$t->integer('qty'); $t->decimal('qty', 10, 2);
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
@ -277,7 +277,7 @@ class ConfideSetupUsersTable extends Migration {
$t->string('product_key'); $t->string('product_key');
$t->string('notes'); $t->string('notes');
$t->decimal('cost', 10, 2); $t->decimal('cost', 10, 2);
$t->integer('qty'); $t->decimal('qty', 10, 2);
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); $t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
$t->foreign('product_id')->references('id')->on('products'); $t->foreign('product_id')->references('id')->on('products');

View File

@ -35,23 +35,23 @@ class Utils
return $phoneNumber; return $phoneNumber;
} }
function pluralize($string, $count) public static function pluralize($string, $count)
{ {
$string = str_replace('?', $count, $string); $string = str_replace('?', $count, $string);
return $count == 1 ? $string : $string . 's'; return $count == 1 ? $string : $string . 's';
} }
function toArray($data) public static function toArray($data)
{ {
return json_decode(json_encode((array) $data), true); return json_decode(json_encode((array) $data), true);
} }
function toSpaceCase($camelStr) public static function toSpaceCase($camelStr)
{ {
return preg_replace('/([a-z])([A-Z])/s','$1 $2', $camelStr); return preg_replace('/([a-z])([A-Z])/s','$1 $2', $camelStr);
} }
function timestampToDateTimeString($timestamp) { public static function timestampToDateTimeString($timestamp) {
$tz = Session::get('tz'); $tz = Session::get('tz');
if (!$tz) { if (!$tz) {
$tz = 'US/Eastern'; $tz = 'US/Eastern';
@ -65,7 +65,7 @@ class Utils
return $date->format('l M jS, Y g:ia'); return $date->format('l M jS, Y g:ia');
} }
function timestampToDateString($timestamp) { public static function timestampToDateString($timestamp) {
$tz = Session::get('tz'); $tz = Session::get('tz');
if (!$tz) { if (!$tz) {
$tz = 'US/Eastern'; $tz = 'US/Eastern';
@ -93,7 +93,7 @@ class Utils
} }
*/ */
function toSqlDate($date) public static function toSqlDate($date)
{ {
if (!$date) if (!$date)
{ {
@ -103,7 +103,7 @@ class Utils
return DateTime::createFromFormat('m/d/Y', $date); return DateTime::createFromFormat('m/d/Y', $date);
} }
function fromSqlDate($date) public static function fromSqlDate($date)
{ {
if (!$date || $date == '0000-00-00') if (!$date || $date == '0000-00-00')
{ {
@ -113,7 +113,7 @@ class Utils
return DateTime::createFromFormat('Y-m-d', $date)->format('m/d/Y'); return DateTime::createFromFormat('Y-m-d', $date)->format('m/d/Y');
} }
function trackViewed($name, $type) public static function trackViewed($name, $type)
{ {
$url = Request::url(); $url = Request::url();
$viewed = Session::get(RECENTLY_VIEWED); $viewed = Session::get(RECENTLY_VIEWED);

View File

@ -6,9 +6,6 @@
{{ Former::open()->addClass('col-md-10 col-md-offset-1') }} {{ Former::open()->addClass('col-md-10 col-md-offset-1') }}
{{ Former::populate($account) }} {{ Former::populate($account) }}
{{ Former::legend('Invoices') }}
{{ Former::textarea('invoice_terms') }}
{{ Former::legend('Payment Gateway') }} {{ Former::legend('Payment Gateway') }}
@if ($accountGateway) @if ($accountGateway)
@ -39,6 +36,9 @@
@endforeach @endforeach
{{ Former::legend('Invoices') }}
{{ Former::textarea('invoice_terms') }}
{{ Former::actions( Button::lg_primary_submit('Save') ) }} {{ Former::actions( Button::lg_primary_submit('Save') ) }}
{{ Former::close() }} {{ Former::close() }}

View File

@ -9,7 +9,8 @@
{{ Former::open($url)->addClass('col-md-10 col-md-offset-1 main_form')->method($method)->rules(array( {{ Former::open($url)->addClass('col-md-10 col-md-offset-1 main_form')->method($method)->rules(array(
'amount' => 'required' 'client' => 'required',
'amount' => 'required',
)); }} )); }}
@if ($credit) @if ($credit)

View File

@ -102,7 +102,10 @@
} }
*/ */
/* table sorting indicators */ /* table sorting indicators */
/*table.table thead .sorting { background: url('images/sort_both.png') no-repeat center right; }*/
/*
table.table thead .sorting, table.table thead .sorting,
table.table thead .sorting_asc, table.table thead .sorting_asc,
table.table thead .sorting_desc, table.table thead .sorting_desc,
@ -112,14 +115,13 @@
*cursor: hand; *cursor: hand;
} }
/*table.table thead .sorting { background: url('images/sort_both.png') no-repeat center right; }*/
table.table thead .sorting_asc { background: url('images/sort_asc.png') no-repeat center right; } table.table thead .sorting_asc { background: url('images/sort_asc.png') no-repeat center right; }
table.table thead .sorting_desc { background: url('images/sort_desc.png') no-repeat center right; } table.table thead .sorting_desc { background: url('images/sort_desc.png') no-repeat center right; }
table.table thead .sorting_asc_disabled { background: url('images/sort_asc_disabled.png') no-repeat center right; } table.table thead .sorting_asc_disabled { background: url('images/sort_asc_disabled.png') no-repeat center right; }
table.table thead .sorting_desc_disabled { background: url('images/sort_desc_disabled.png') no-repeat center right; } table.table thead .sorting_desc_disabled { background: url('images/sort_desc_disabled.png') no-repeat center right; }
*/
/* Hover nav */ /* Hover nav */
@ -195,6 +197,10 @@
border-style: none !important; border-style: none !important;
} }
.invoice-table td.td-icon {
vertical-align: middle !important;
}
.fa-bars { .fa-bars {
cursor: move !important; cursor: move !important;
} }

View File

@ -1,10 +1,18 @@
@extends('header') @extends('header')
@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
@section('content') @section('content')
<p>&nbsp;</p> <p>&nbsp;</p>
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array( {{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
'client' => 'required',
'invoice_number' => 'required', 'invoice_number' => 'required',
'invoice_date' => 'required', 'invoice_date' => 'required',
'product_key' => 'max:14', 'product_key' => 'max:14',
@ -55,9 +63,8 @@
</thead> </thead>
<tbody data-bind="sortable: { data: items, afterMove: onDragged }"> <tbody data-bind="sortable: { data: items, afterMove: onDragged }">
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row"> <tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
<td style="width:20px;" class="hide-border"> <td style="width:20px;" class="hide-border td-icon">
<!-- <i data-bind="click: $parent.addItem, visible: actionsVisible" class="fa fa-plus-circle" style="cursor:pointer" title="Add item"></i>&nbsp; --> <i data-bind="visible: actionsVisible() &amp;&amp; $parent.items().length > 1" class="fa fa-sort"></i>
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
</td> </td>
<td style="width:120px"> <td style="width:120px">
{{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'key')->onkeyup('onChange()') {{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'key')->onkeyup('onChange()')
@ -80,7 +87,7 @@
<td style="width:100px;text-align: right;padding-top:9px !important"> <td style="width:100px;text-align: right;padding-top:9px !important">
<span data-bind="text: total"></span> <span data-bind="text: total"></span>
</td> </td>
<td style="width:20px; cursor:pointer" class="hide-border"> <td style="width:20px; cursor:pointer" class="hide-border td-icon">
&nbsp;<i data-bind="click: $parent.removeItem, visible: actionsVisible() &amp;&amp; $parent.items().length > 1" class="fa fa-minus-circle" title="Remove item"/> &nbsp;<i data-bind="click: $parent.removeItem, visible: actionsVisible() &amp;&amp; $parent.items().length > 1" class="fa fa-minus-circle" title="Remove item"/>
</td> </td>
</tr> </tr>
@ -145,7 +152,8 @@
<!-- <textarea rows="20" cols="120" id="pdfText" onkeyup="runCode()"></textarea> --> <!-- <textarea rows="20" cols="120" id="pdfText" onkeyup="runCode()"></textarea> -->
<!-- <iframe frameborder="1" width="100%" height="600" style="display:block;margin: 0 auto"></iframe> --> <!-- <iframe frameborder="1" width="100%" height="600" style="display:block;margin: 0 auto"></iframe> -->
<iframe frameborder="1" width="100%" height="500"></iframe> <!-- <iframe frameborder="1" width="100%" height="500"></iframe> -->
<canvas id="the-canvas" style="width:100%"></canvas>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
@ -247,8 +255,9 @@
$input.combobox(); $input.combobox();
$('.client_select input.form-control').on('change', function(e) { $('.client_select input.form-control').on('change', function(e) {
refreshPDF(); refreshPDF();
}).on('keydown', function() { if ($('input[name=client]').val() != '-1') {
$('#modalLink').text('Create new client'); $('#modalLink').text('Create new client');
}
}); });
//enableHoverClick($('.combobox-container input.form-control'), $('.combobox-container input[name=client]'), '{{ URL::to('clients') }}'); //enableHoverClick($('.combobox-container input.form-control'), $('.combobox-container input[name=client]'), '{{ URL::to('clients') }}');
@ -280,7 +289,6 @@
}); });
function showCreateNew() { function showCreateNew() {
console.log('showCreateNew: %s', $('input[name=client]').val());
if ($('input[name=client]').val() != '-1') { if ($('input[name=client]').val() != '-1') {
$('#myModal input').val(''); $('#myModal input').val('');
$('#myModal #country_id').val(''); $('#myModal #country_id').val('');
@ -340,8 +348,7 @@
}; };
var clientId = $('input[name=client]').val(); var clientId = $('input[name=client]').val();
console.log('clientId: %s', clientId);
console.log('mapped: %s', clientMap[clientId]);
if (clientId == '-1') { if (clientId == '-1') {
var client = { var client = {
name: $('#name').val(), name: $('#name').val(),
@ -378,11 +385,46 @@
}, 100); }, 100);
} }
var BASE64_MARKER = ';base64,';
function convertDataURIToBinary(dataURI) {
var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
var base64 = dataURI.substring(base64Index);
var raw = window.atob(base64);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));
for(i = 0; i < rawLength; i++) {
array[i] = raw.charCodeAt(i);
}
return array;
}
function _refreshPDF() { function _refreshPDF() {
var invoice = createInvoiceModel(); var invoice = createInvoiceModel();
var doc = generatePDF(invoice); var doc = generatePDF(invoice);
var string = doc.output('datauristring'); var string = doc.output('dataurlstring');
$('iframe').attr('src', string);
//console.log(string);
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);
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({canvasContext: context, viewport: viewport});
});
});
//$('iframe').attr('src', string);
} }
function onDownloadClick() { function onDownloadClick() {
@ -415,6 +457,7 @@
if (!name) { if (!name) {
if (!name) $('#nameError').css( "display", "inline" ); if (!name) $('#nameError').css( "display", "inline" );
} else { } else {
$('select#client').combobox('setSelected');
$('input[name=client]').val('-1'); $('input[name=client]').val('-1');
$('.client_select input.form-control').val(name); $('.client_select input.form-control').val(name);
$('.client_select').addClass('combobox-selected'); $('.client_select').addClass('combobox-selected');
@ -422,7 +465,7 @@
$('#nameError').css( "display", "none" ); $('#nameError').css( "display", "none" );
$('#modalLink').text('Edit client details'); $('#modalLink').text('Edit client details');
$('#myModal').modal('hide'); $('#myModal').modal('hide');
$('input#invoice_number').focus(); $('.client_select input.form-control').focus();
//$('[name="client_combobox"]').focus(); //$('[name="client_combobox"]').focus();
refreshPDF(); refreshPDF();
@ -525,7 +568,7 @@
this.rawTotal = ko.computed(function() { this.rawTotal = ko.computed(function() {
var cost = parseFloat(self.cost()); var cost = parseFloat(self.cost());
var qty = parseInt(self.qty()); var qty = parseFloat(self.qty());
var tax = parseFloat(self.tax()); var tax = parseFloat(self.tax());
var value = cost * qty; var value = cost * qty;
if (self.tax() > 0) { if (self.tax() > 0) {

View File

@ -9,7 +9,8 @@
{{ Former::open($url)->addClass('col-md-10 col-md-offset-1 main_form')->method($method)->rules(array( {{ Former::open($url)->addClass('col-md-10 col-md-offset-1 main_form')->method($method)->rules(array(
'amount' => 'required' 'client' => 'required',
'amount' => 'required',
)); }} )); }}
@if ($payment) @if ($payment)
@ -105,7 +106,6 @@
} }
$('select#invoice').combobox('refresh'); $('select#invoice').combobox('refresh');
}).trigger('change'); }).trigger('change');
//enableHoverClick($('.client-select input.form-control'), $('input[name=client]'), '{{ URL::to('clients') }}');
$input.combobox(); $input.combobox();
var $input = $('select#invoice').on('change', function(e) { var $input = $('select#invoice').on('change', function(e) {
@ -114,10 +114,8 @@
if (invoiceId) { if (invoiceId) {
var client = clientMap[invoiceId]; var client = clientMap[invoiceId];
setComboboxValue($('.client-select'), client.public_id, client.name); setComboboxValue($('.client-select'), client.public_id, client.name);
//setComboboxValue($('select#client'), client.public_id, client.name);
} }
}); });
//enableHoverClick($('.invoice-select input.form-control'), $('input[name=invoice]'), '{{ URL::to('invoices') }}');
$input.combobox(); $input.combobox();
$('#payment_date').datepicker({ $('#payment_date').datepicker({

View File

@ -96,6 +96,10 @@
this.$source.removeAttr('required'); this.$source.removeAttr('required');
} }
, setSelected: function() {
this.selected = true;
}
, select: function () { , select: function () {
var val = this.$menu.find('.active').attr('data-value'); var val = this.$menu.find('.active').attr('data-value');
this.$element.val(this.updater(val)).trigger('change'); this.$element.val(this.updater(val)).trigger('change');

483
public/js/compatibility.js Executable file
View File

@ -0,0 +1,483 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals VBArray, PDFJS */
'use strict';
// Initializing PDFJS global object here, it case if we need to change/disable
// some PDF.js features, e.g. range requests
if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
// Checking if the typed arrays are supported
(function checkTypedArrayCompatibility() {
if (typeof Uint8Array !== 'undefined') {
// some mobile versions do not support subarray (e.g. safari 5 / iOS)
if (typeof Uint8Array.prototype.subarray === 'undefined') {
Uint8Array.prototype.subarray = function subarray(start, end) {
return new Uint8Array(this.slice(start, end));
};
Float32Array.prototype.subarray = function subarray(start, end) {
return new Float32Array(this.slice(start, end));
};
}
// some mobile version might not support Float64Array
if (typeof Float64Array === 'undefined')
window.Float64Array = Float32Array;
return;
}
function subarray(start, end) {
return new TypedArray(this.slice(start, end));
}
function setArrayOffset(array, offset) {
if (arguments.length < 2)
offset = 0;
for (var i = 0, n = array.length; i < n; ++i, ++offset)
this[offset] = array[i] & 0xFF;
}
function TypedArray(arg1) {
var result;
if (typeof arg1 === 'number') {
result = [];
for (var i = 0; i < arg1; ++i)
result[i] = 0;
} else if ('slice' in arg1) {
result = arg1.slice(0);
} else {
result = [];
for (var i = 0, n = arg1.length; i < n; ++i) {
result[i] = arg1[i];
}
}
result.subarray = subarray;
result.buffer = result;
result.byteLength = result.length;
result.set = setArrayOffset;
if (typeof arg1 === 'object' && arg1.buffer)
result.buffer = arg1.buffer;
return result;
}
window.Uint8Array = TypedArray;
// we don't need support for set, byteLength for 32-bit array
// so we can use the TypedArray as well
window.Uint32Array = TypedArray;
window.Int32Array = TypedArray;
window.Uint16Array = TypedArray;
window.Float32Array = TypedArray;
window.Float64Array = TypedArray;
})();
// URL = URL || webkitURL
(function normalizeURLObject() {
if (!window.URL) {
window.URL = window.webkitURL;
}
})();
// Object.create() ?
(function checkObjectCreateCompatibility() {
if (typeof Object.create !== 'undefined')
return;
Object.create = function objectCreate(proto) {
function Constructor() {}
Constructor.prototype = proto;
return new Constructor();
};
})();
// Object.defineProperty() ?
(function checkObjectDefinePropertyCompatibility() {
if (typeof Object.defineProperty !== 'undefined') {
var definePropertyPossible = true;
try {
// some browsers (e.g. safari) cannot use defineProperty() on DOM objects
// and thus the native version is not sufficient
Object.defineProperty(new Image(), 'id', { value: 'test' });
// ... another test for android gb browser for non-DOM objects
var Test = function Test() {};
Test.prototype = { get id() { } };
Object.defineProperty(new Test(), 'id',
{ value: '', configurable: true, enumerable: true, writable: false });
} catch (e) {
definePropertyPossible = false;
}
if (definePropertyPossible) return;
}
Object.defineProperty = function objectDefineProperty(obj, name, def) {
delete obj[name];
if ('get' in def)
obj.__defineGetter__(name, def['get']);
if ('set' in def)
obj.__defineSetter__(name, def['set']);
if ('value' in def) {
obj.__defineSetter__(name, function objectDefinePropertySetter(value) {
this.__defineGetter__(name, function objectDefinePropertyGetter() {
return value;
});
return value;
});
obj[name] = def.value;
}
};
})();
// Object.keys() ?
(function checkObjectKeysCompatibility() {
if (typeof Object.keys !== 'undefined')
return;
Object.keys = function objectKeys(obj) {
var result = [];
for (var i in obj) {
if (obj.hasOwnProperty(i))
result.push(i);
}
return result;
};
})();
// No readAsArrayBuffer ?
(function checkFileReaderReadAsArrayBuffer() {
if (typeof FileReader === 'undefined')
return; // FileReader is not implemented
var frPrototype = FileReader.prototype;
// Older versions of Firefox might not have readAsArrayBuffer
if ('readAsArrayBuffer' in frPrototype)
return; // readAsArrayBuffer is implemented
Object.defineProperty(frPrototype, 'readAsArrayBuffer', {
value: function fileReaderReadAsArrayBuffer(blob) {
var fileReader = new FileReader();
var originalReader = this;
fileReader.onload = function fileReaderOnload(evt) {
var data = evt.target.result;
var buffer = new ArrayBuffer(data.length);
var uint8Array = new Uint8Array(buffer);
for (var i = 0, ii = data.length; i < ii; i++)
uint8Array[i] = data.charCodeAt(i);
Object.defineProperty(originalReader, 'result', {
value: buffer,
enumerable: true,
writable: false,
configurable: true
});
var event = document.createEvent('HTMLEvents');
event.initEvent('load', false, false);
originalReader.dispatchEvent(event);
};
fileReader.readAsBinaryString(blob);
}
});
})();
// No XMLHttpRequest.response ?
(function checkXMLHttpRequestResponseCompatibility() {
var xhrPrototype = XMLHttpRequest.prototype;
if (!('overrideMimeType' in xhrPrototype)) {
// IE10 might have response, but not overrideMimeType
Object.defineProperty(xhrPrototype, 'overrideMimeType', {
value: function xmlHttpRequestOverrideMimeType(mimeType) {}
});
}
if ('response' in xhrPrototype ||
'mozResponseArrayBuffer' in xhrPrototype ||
'mozResponse' in xhrPrototype ||
'responseArrayBuffer' in xhrPrototype)
return;
// IE9 ?
if (typeof VBArray !== 'undefined') {
Object.defineProperty(xhrPrototype, 'response', {
get: function xmlHttpRequestResponseGet() {
return new Uint8Array(new VBArray(this.responseBody).toArray());
}
});
return;
}
// other browsers
function responseTypeSetter() {
// will be only called to set "arraybuffer"
this.overrideMimeType('text/plain; charset=x-user-defined');
}
if (typeof xhrPrototype.overrideMimeType === 'function') {
Object.defineProperty(xhrPrototype, 'responseType',
{ set: responseTypeSetter });
}
function responseGetter() {
var text = this.responseText;
var i, n = text.length;
var result = new Uint8Array(n);
for (i = 0; i < n; ++i)
result[i] = text.charCodeAt(i) & 0xFF;
return result;
}
Object.defineProperty(xhrPrototype, 'response', { get: responseGetter });
})();
// window.btoa (base64 encode function) ?
(function checkWindowBtoaCompatibility() {
if ('btoa' in window)
return;
var digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
window.btoa = function windowBtoa(chars) {
var buffer = '';
var i, n;
for (i = 0, n = chars.length; i < n; i += 3) {
var b1 = chars.charCodeAt(i) & 0xFF;
var b2 = chars.charCodeAt(i + 1) & 0xFF;
var b3 = chars.charCodeAt(i + 2) & 0xFF;
var d1 = b1 >> 2, d2 = ((b1 & 3) << 4) | (b2 >> 4);
var d3 = i + 1 < n ? ((b2 & 0xF) << 2) | (b3 >> 6) : 64;
var d4 = i + 2 < n ? (b3 & 0x3F) : 64;
buffer += (digits.charAt(d1) + digits.charAt(d2) +
digits.charAt(d3) + digits.charAt(d4));
}
return buffer;
};
})();
// window.atob (base64 encode function) ?
(function checkWindowAtobCompatibility() {
if ('atob' in window)
return;
// https://github.com/davidchambers/Base64.js
var digits =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
window.atob = function (input) {
input = input.replace(/=+$/, '');
if (input.length % 4 == 1) throw new Error('bad atob input');
for (
// initialize result and counters
var bc = 0, bs, buffer, idx = 0, output = '';
// get next character
buffer = input.charAt(idx++);
// character found in table?
// initialize bit storage and add its ascii value
~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
// and if not first of each 4 characters,
// convert the first 8 bits to one ascii character
bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
) {
// try to find character in table (0-63, not found => -1)
buffer = digits.indexOf(buffer);
}
return output;
};
})();
// Function.prototype.bind ?
(function checkFunctionPrototypeBindCompatibility() {
if (typeof Function.prototype.bind !== 'undefined')
return;
Function.prototype.bind = function functionPrototypeBind(obj) {
var fn = this, headArgs = Array.prototype.slice.call(arguments, 1);
var bound = function functionPrototypeBindBound() {
var args = Array.prototype.concat.apply(headArgs, arguments);
return fn.apply(obj, args);
};
return bound;
};
})();
// HTMLElement dataset property
(function checkDatasetProperty() {
var div = document.createElement('div');
if ('dataset' in div)
return; // dataset property exists
Object.defineProperty(HTMLElement.prototype, 'dataset', {
get: function() {
if (this._dataset)
return this._dataset;
var dataset = {};
for (var j = 0, jj = this.attributes.length; j < jj; j++) {
var attribute = this.attributes[j];
if (attribute.name.substring(0, 5) != 'data-')
continue;
var key = attribute.name.substring(5).replace(/\-([a-z])/g,
function(all, ch) { return ch.toUpperCase(); });
dataset[key] = attribute.value;
}
Object.defineProperty(this, '_dataset', {
value: dataset,
writable: false,
enumerable: false
});
return dataset;
},
enumerable: true
});
})();
// HTMLElement classList property
(function checkClassListProperty() {
var div = document.createElement('div');
if ('classList' in div)
return; // classList property exists
function changeList(element, itemName, add, remove) {
var s = element.className || '';
var list = s.split(/\s+/g);
if (list[0] === '') list.shift();
var index = list.indexOf(itemName);
if (index < 0 && add)
list.push(itemName);
if (index >= 0 && remove)
list.splice(index, 1);
element.className = list.join(' ');
return (index >= 0);
}
var classListPrototype = {
add: function(name) {
changeList(this.element, name, true, false);
},
contains: function(name) {
return changeList(this.element, name, false, false);
},
remove: function(name) {
changeList(this.element, name, false, true);
},
toggle: function(name) {
changeList(this.element, name, true, true);
}
};
Object.defineProperty(HTMLElement.prototype, 'classList', {
get: function() {
if (this._classList)
return this._classList;
var classList = Object.create(classListPrototype, {
element: {
value: this,
writable: false,
enumerable: true
}
});
Object.defineProperty(this, '_classList', {
value: classList,
writable: false,
enumerable: false
});
return classList;
},
enumerable: true
});
})();
// Check console compatibility
(function checkConsoleCompatibility() {
if (!('console' in window)) {
window.console = {
log: function() {},
error: function() {},
warn: function() {}
};
} else if (!('bind' in console.log)) {
// native functions in IE9 might not have bind
console.log = (function(fn) {
return function(msg) { return fn(msg); };
})(console.log);
console.error = (function(fn) {
return function(msg) { return fn(msg); };
})(console.error);
console.warn = (function(fn) {
return function(msg) { return fn(msg); };
})(console.warn);
}
})();
// Check onclick compatibility in Opera
(function checkOnClickCompatibility() {
// workaround for reported Opera bug DSK-354448:
// onclick fires on disabled buttons with opaque content
function ignoreIfTargetDisabled(event) {
if (isDisabled(event.target)) {
event.stopPropagation();
}
}
function isDisabled(node) {
return node.disabled || (node.parentNode && isDisabled(node.parentNode));
}
if (navigator.userAgent.indexOf('Opera') != -1) {
// use browser detection since we cannot feature-check this bug
document.addEventListener('click', ignoreIfTargetDisabled, true);
}
})();
// Checks if navigator.language is supported
(function checkNavigatorLanguage() {
if ('language' in navigator)
return;
Object.defineProperty(navigator, 'language', {
get: function navigatorLanguage() {
var language = navigator.userLanguage || 'en-US';
return language.substring(0, 2).toLowerCase() +
language.substring(2).toUpperCase();
},
enumerable: true
});
})();
(function checkRangeRequests() {
// Safari has issues with cached range requests see:
// https://github.com/mozilla/pdf.js/issues/3260
// Last tested with version 6.0.4.
var isSafari = Object.prototype.toString.call(
window.HTMLElement).indexOf('Constructor') > 0;
// Older versions of Android (pre 3.0) has issues with range requests, see:
// https://github.com/mozilla/pdf.js/issues/3381.
// Make sure that we only match webkit-based Android browsers,
// since Firefox/Fennec works as expected.
var regex = /Android\s[0-2][^\d]/;
var isOldAndroid = regex.test(navigator.userAgent);
if (isSafari || isOldAndroid) {
PDFJS.disableRange = true;
}
})();
// Check if the browser supports manipulation of the history.
(function checkHistoryManipulation() {
if (!window.history.pushState) {
PDFJS.disableHistory = true;
}
})();

49
public/js/pdf.js Executable file
View File

@ -0,0 +1,49 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Initializing PDFJS global object (if still undefined)
if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
//#if BUNDLE_VERSION
//#expand PDFJS.version = '__BUNDLE_VERSION__';
//#endif
//#if BUNDLE_BUILD
//#expand PDFJS.build = '__BUNDLE_BUILD__';
//#endif
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
'use strict';
//#expand __BUNDLE__
}).call((typeof window === 'undefined') ? this : window);
//#if !(MOZCENTRAL || FIREFOX)
if (!PDFJS.workerSrc && typeof document !== 'undefined') {
// workerSrc is not set -- using last script url to define default location
PDFJS.workerSrc = (function () {
'use strict';
var scriptTagContainer = document.body ||
document.getElementsByTagName('head')[0];
var pdfjsSrc = scriptTagContainer.lastChild.src;
return pdfjsSrc && pdfjsSrc.replace(/\.js$/i, '.worker.js');
})();
}
//#endif

7420
public/js/pdf_viewer.js Executable file

File diff suppressed because it is too large Load Diff

39769
public/js/pdf_viewer.worker.js Executable file

File diff suppressed because it is too large Load Diff

View File

@ -86,7 +86,7 @@ function generatePDF(invoice) {
for(var i=0; i<invoice.invoice_items.length; i++) { for(var i=0; i<invoice.invoice_items.length; i++) {
var item = invoice.invoice_items[i]; var item = invoice.invoice_items[i];
var cost = formatNumber(item.cost); var cost = formatNumber(item.cost);
var qty = item.qty ? parseInt(item.qty, 10) + '' : ''; var qty = item.qty ? parseFloat(item.qty) + '' : '';
var notes = item.notes; var notes = item.notes;
var productKey = item.product_key; var productKey = item.product_key;
@ -430,16 +430,12 @@ function setAsLink($input, enable) {
} }
function setComboboxValue($combobox, id, name) { function setComboboxValue($combobox, id, name) {
console.log('id: ' + id);
$combobox.find('input').val(id); $combobox.find('input').val(id);
$combobox.find('input.form-control').val(name); $combobox.find('input.form-control').val(name);
if (id && name) { if (id && name) {
//console.log('%s %s', $combobox.find('select')[0], id); $combobox.find('select').combobox('setSelected');
//$combobox.find('select').val(id).prop('selected', 'selected');
$combobox.find('.combobox-container').addClass('combobox-selected'); $combobox.find('.combobox-container').addClass('combobox-selected');
} else { } else {
//$combobox.find('select').val('');
$combobox.find('.combobox-container').removeClass('combobox-selected'); $combobox.find('.combobox-container').removeClass('combobox-selected');
} }
//console.log($combobox).combobox('');
} }