mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-17 16:42:48 +01:00
Floats Handling and PDF.js support
This commit is contained in:
parent
b7f09685d0
commit
ccd7a9f3a7
@ -370,7 +370,7 @@ class InvoiceController extends \BaseController {
|
||||
$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)
|
||||
@ -415,7 +415,7 @@ class InvoiceController extends \BaseController {
|
||||
$invoiceItem->product_key = trim($item->product_key);
|
||||
$invoiceItem->notes = trim($item->notes);
|
||||
$invoiceItem->cost = floatval($item->cost);
|
||||
$invoiceItem->qty = intval($item->qty);
|
||||
$invoiceItem->qty = floatval($item->qty);
|
||||
|
||||
$invoice->invoice_items()->save($invoiceItem);
|
||||
}
|
||||
|
@ -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); });
|
||||
}
|
||||
|
||||
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('payment_date', function($model) { return Utils::timestampToDateString($model->payment_date); })
|
||||
->addColumn('dropdown', function($model)
|
||||
|
@ -256,7 +256,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->string('product_key');
|
||||
$t->string('notes');
|
||||
$t->decimal('cost', 10, 2);
|
||||
$t->integer('qty');
|
||||
$t->decimal('qty', 10, 2);
|
||||
|
||||
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||
|
||||
@ -277,7 +277,7 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->string('product_key');
|
||||
$t->string('notes');
|
||||
$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('product_id')->references('id')->on('products');
|
||||
|
@ -35,23 +35,23 @@ class Utils
|
||||
return $phoneNumber;
|
||||
}
|
||||
|
||||
function pluralize($string, $count)
|
||||
public static function pluralize($string, $count)
|
||||
{
|
||||
$string = str_replace('?', $count, $string);
|
||||
return $count == 1 ? $string : $string . 's';
|
||||
}
|
||||
|
||||
function toArray($data)
|
||||
public static function toArray($data)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
function timestampToDateTimeString($timestamp) {
|
||||
public static function timestampToDateTimeString($timestamp) {
|
||||
$tz = Session::get('tz');
|
||||
if (!$tz) {
|
||||
$tz = 'US/Eastern';
|
||||
@ -65,7 +65,7 @@ class Utils
|
||||
return $date->format('l M jS, Y g:ia');
|
||||
}
|
||||
|
||||
function timestampToDateString($timestamp) {
|
||||
public static function timestampToDateString($timestamp) {
|
||||
$tz = Session::get('tz');
|
||||
if (!$tz) {
|
||||
$tz = 'US/Eastern';
|
||||
@ -93,7 +93,7 @@ class Utils
|
||||
}
|
||||
*/
|
||||
|
||||
function toSqlDate($date)
|
||||
public static function toSqlDate($date)
|
||||
{
|
||||
if (!$date)
|
||||
{
|
||||
@ -103,7 +103,7 @@ class Utils
|
||||
return DateTime::createFromFormat('m/d/Y', $date);
|
||||
}
|
||||
|
||||
function fromSqlDate($date)
|
||||
public static function fromSqlDate($date)
|
||||
{
|
||||
if (!$date || $date == '0000-00-00')
|
||||
{
|
||||
@ -113,7 +113,7 @@ class Utils
|
||||
return DateTime::createFromFormat('Y-m-d', $date)->format('m/d/Y');
|
||||
}
|
||||
|
||||
function trackViewed($name, $type)
|
||||
public static function trackViewed($name, $type)
|
||||
{
|
||||
$url = Request::url();
|
||||
$viewed = Session::get(RECENTLY_VIEWED);
|
||||
|
@ -6,9 +6,6 @@
|
||||
{{ Former::open()->addClass('col-md-10 col-md-offset-1') }}
|
||||
{{ Former::populate($account) }}
|
||||
|
||||
{{ Former::legend('Invoices') }}
|
||||
{{ Former::textarea('invoice_terms') }}
|
||||
|
||||
{{ Former::legend('Payment Gateway') }}
|
||||
|
||||
@if ($accountGateway)
|
||||
@ -39,6 +36,9 @@
|
||||
@endforeach
|
||||
|
||||
|
||||
{{ Former::legend('Invoices') }}
|
||||
{{ Former::textarea('invoice_terms') }}
|
||||
|
||||
{{ Former::actions( Button::lg_primary_submit('Save') ) }}
|
||||
{{ Former::close() }}
|
||||
|
||||
|
@ -9,7 +9,8 @@
|
||||
|
||||
|
||||
{{ 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)
|
||||
|
@ -102,7 +102,10 @@
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/* 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_asc,
|
||||
table.table thead .sorting_desc,
|
||||
@ -112,14 +115,13 @@
|
||||
*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_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_desc_disabled { background: url('images/sort_desc_disabled.png') no-repeat center right; }
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* Hover nav */
|
||||
@ -195,6 +197,10 @@
|
||||
border-style: none !important;
|
||||
}
|
||||
|
||||
.invoice-table td.td-icon {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
|
||||
.fa-bars {
|
||||
cursor: move !important;
|
||||
}
|
||||
|
@ -1,10 +1,18 @@
|
||||
@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')
|
||||
|
||||
<p> </p>
|
||||
|
||||
{{ Former::open($url)->method($method)->addClass('main_form')->rules(array(
|
||||
'client' => 'required',
|
||||
'invoice_number' => 'required',
|
||||
'invoice_date' => 'required',
|
||||
'product_key' => 'max:14',
|
||||
@ -55,9 +63,8 @@
|
||||
</thead>
|
||||
<tbody data-bind="sortable: { data: items, afterMove: onDragged }">
|
||||
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
|
||||
<td style="width:20px;" class="hide-border">
|
||||
<!-- <i data-bind="click: $parent.addItem, visible: actionsVisible" class="fa fa-plus-circle" style="cursor:pointer" title="Add item"></i> -->
|
||||
<i data-bind="visible: actionsVisible" class="fa fa-sort"></i>
|
||||
<td style="width:20px;" class="hide-border td-icon">
|
||||
<i data-bind="visible: actionsVisible() && $parent.items().length > 1" class="fa fa-sort"></i>
|
||||
</td>
|
||||
<td style="width:120px">
|
||||
{{ 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">
|
||||
<span data-bind="text: total"></span>
|
||||
</td>
|
||||
<td style="width:20px; cursor:pointer" class="hide-border">
|
||||
<td style="width:20px; cursor:pointer" class="hide-border td-icon">
|
||||
<i data-bind="click: $parent.removeItem, visible: actionsVisible() && $parent.items().length > 1" class="fa fa-minus-circle" title="Remove item"/>
|
||||
</td>
|
||||
</tr>
|
||||
@ -145,7 +152,8 @@
|
||||
|
||||
<!-- <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="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">
|
||||
@ -245,10 +253,11 @@
|
||||
|
||||
var $input = $('select#client');
|
||||
$input.combobox();
|
||||
$('.client_select input.form-control').on('change', function(e) {
|
||||
$('.client_select input.form-control').on('change', function(e) {
|
||||
refreshPDF();
|
||||
}).on('keydown', function() {
|
||||
$('#modalLink').text('Create new client');
|
||||
if ($('input[name=client]').val() != '-1') {
|
||||
$('#modalLink').text('Create new client');
|
||||
}
|
||||
});
|
||||
//enableHoverClick($('.combobox-container input.form-control'), $('.combobox-container input[name=client]'), '{{ URL::to('clients') }}');
|
||||
|
||||
@ -280,7 +289,6 @@
|
||||
});
|
||||
|
||||
function showCreateNew() {
|
||||
console.log('showCreateNew: %s', $('input[name=client]').val());
|
||||
if ($('input[name=client]').val() != '-1') {
|
||||
$('#myModal input').val('');
|
||||
$('#myModal #country_id').val('');
|
||||
@ -340,8 +348,7 @@
|
||||
};
|
||||
|
||||
var clientId = $('input[name=client]').val();
|
||||
console.log('clientId: %s', clientId);
|
||||
console.log('mapped: %s', clientMap[clientId]);
|
||||
|
||||
if (clientId == '-1') {
|
||||
var client = {
|
||||
name: $('#name').val(),
|
||||
@ -378,11 +385,46 @@
|
||||
}, 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() {
|
||||
var invoice = createInvoiceModel();
|
||||
var doc = generatePDF(invoice);
|
||||
var string = doc.output('datauristring');
|
||||
$('iframe').attr('src', string);
|
||||
var string = doc.output('dataurlstring');
|
||||
|
||||
//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() {
|
||||
@ -415,6 +457,7 @@
|
||||
if (!name) {
|
||||
if (!name) $('#nameError').css( "display", "inline" );
|
||||
} else {
|
||||
$('select#client').combobox('setSelected');
|
||||
$('input[name=client]').val('-1');
|
||||
$('.client_select input.form-control').val(name);
|
||||
$('.client_select').addClass('combobox-selected');
|
||||
@ -422,7 +465,7 @@
|
||||
$('#nameError').css( "display", "none" );
|
||||
$('#modalLink').text('Edit client details');
|
||||
$('#myModal').modal('hide');
|
||||
$('input#invoice_number').focus();
|
||||
$('.client_select input.form-control').focus();
|
||||
//$('[name="client_combobox"]').focus();
|
||||
|
||||
refreshPDF();
|
||||
@ -525,7 +568,7 @@
|
||||
|
||||
this.rawTotal = ko.computed(function() {
|
||||
var cost = parseFloat(self.cost());
|
||||
var qty = parseInt(self.qty());
|
||||
var qty = parseFloat(self.qty());
|
||||
var tax = parseFloat(self.tax());
|
||||
var value = cost * qty;
|
||||
if (self.tax() > 0) {
|
||||
|
@ -9,7 +9,8 @@
|
||||
|
||||
|
||||
{{ 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)
|
||||
@ -105,7 +106,6 @@
|
||||
}
|
||||
$('select#invoice').combobox('refresh');
|
||||
}).trigger('change');
|
||||
//enableHoverClick($('.client-select input.form-control'), $('input[name=client]'), '{{ URL::to('clients') }}');
|
||||
$input.combobox();
|
||||
|
||||
var $input = $('select#invoice').on('change', function(e) {
|
||||
@ -113,11 +113,9 @@
|
||||
var invoiceId = $('input[name=invoice]').val();
|
||||
if (invoiceId) {
|
||||
var client = clientMap[invoiceId];
|
||||
setComboboxValue($('.client-select'), client.public_id, client.name);
|
||||
//setComboboxValue($('select#client'), client.public_id, client.name);
|
||||
setComboboxValue($('.client-select'), client.public_id, client.name);
|
||||
}
|
||||
});
|
||||
//enableHoverClick($('.invoice-select input.form-control'), $('input[name=invoice]'), '{{ URL::to('invoices') }}');
|
||||
$input.combobox();
|
||||
|
||||
$('#payment_date').datepicker({
|
||||
|
4
public/js/bootstrap-combobox.js
vendored
4
public/js/bootstrap-combobox.js
vendored
@ -96,6 +96,10 @@
|
||||
this.$source.removeAttr('required');
|
||||
}
|
||||
|
||||
, setSelected: function() {
|
||||
this.selected = true;
|
||||
}
|
||||
|
||||
, select: function () {
|
||||
var val = this.$menu.find('.active').attr('data-value');
|
||||
this.$element.val(this.updater(val)).trigger('change');
|
||||
|
483
public/js/compatibility.js
Executable file
483
public/js/compatibility.js
Executable 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
49
public/js/pdf.js
Executable 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
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
39769
public/js/pdf_viewer.worker.js
Executable file
File diff suppressed because it is too large
Load Diff
@ -86,7 +86,7 @@ function generatePDF(invoice) {
|
||||
for(var i=0; i<invoice.invoice_items.length; i++) {
|
||||
var item = invoice.invoice_items[i];
|
||||
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 productKey = item.product_key;
|
||||
|
||||
@ -430,16 +430,12 @@ function setAsLink($input, enable) {
|
||||
}
|
||||
|
||||
function setComboboxValue($combobox, id, name) {
|
||||
console.log('id: ' + id);
|
||||
$combobox.find('input').val(id);
|
||||
$combobox.find('input.form-control').val(name);
|
||||
if (id && name) {
|
||||
//console.log('%s %s', $combobox.find('select')[0], id);
|
||||
//$combobox.find('select').val(id).prop('selected', 'selected');
|
||||
$combobox.find('select').combobox('setSelected');
|
||||
$combobox.find('.combobox-container').addClass('combobox-selected');
|
||||
} else {
|
||||
//$combobox.find('select').val('');
|
||||
$combobox.find('.combobox-container').removeClass('combobox-selected');
|
||||
}
|
||||
//console.log($combobox).combobox('');
|
||||
}
|
Loading…
Reference in New Issue
Block a user