diff --git a/compensation/templates/compensation/detail/compensation/view.html b/compensation/templates/compensation/detail/compensation/view.html index 8e1b1267..026a6ff6 100644 --- a/compensation/templates/compensation/detail/compensation/view.html +++ b/compensation/templates/compensation/detail/compensation/view.html @@ -119,7 +119,9 @@
+ * The destination magnification factor can also be specified when goto is a page number or a named destination. (see documentation below) + * (set magFactor in options). XYZ is the default. + *
+ *+ * Links, Text, Popup, and FreeText are supported. + *
+ *+ * Options In PDF spec Not Implemented Yet + *
If pageNumber is specified, top and zoom may also be specified
+ */ + jsPDFAPI.link = function (x, y, w, h, options) { + 'use strict'; + + this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({ + x: x, + y: y, + w: w, + h: h, + options: options, + type: 'link' + }); + }; + + /** + * valid options + *If pageNumber is specified, top and zoom may also be specified
+ */ + jsPDFAPI.link = function (x, y, w, h, options) { + 'use strict'; + + this.annotationPlugin.annotations[this.internal.getCurrentPageInfo().pageNumber].push({ + x: x, + y: y, + w: w, + h: h, + options: options, + type: 'link' + }); + }; + + /** + * Currently only supports single line text. + * Returns the width of the text/link + */ + jsPDFAPI.textWithLink = function (text, x, y, options) { + 'use strict'; + + var width = this.getTextWidth(text); + var height = this.internal.getLineHeight(); + this.text(text, x, y); + //TODO We really need the text baseline height to do this correctly. + // Or ability to draw text on top, bottom, center, or baseline. + y += height * .2; + this.link(x, y - height, width, height, options); + return width; + }; + + //TODO move into external library + jsPDFAPI.getTextWidth = function (text) { + 'use strict'; + + var fontSize = this.internal.getFontSize(); + var txtWidth = this.getStringUnitWidth(text) * fontSize / this.internal.scaleFactor; + return txtWidth; + }; + + //TODO move into external library + jsPDFAPI.getLineHeight = function () { + return this.internal.getLineHeight(); + }; + + return this; +})(jsPDF.API); + +/** + * jsPDF Autoprint Plugin + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + +(function (jsPDFAPI) { + 'use strict'; + + jsPDFAPI.autoPrint = function () { + 'use strict'; + + var refAutoPrintTag; + + this.internal.events.subscribe('postPutResources', function () { + refAutoPrintTag = this.internal.newObject(); + this.internal.write("<< /S/Named /Type/Action /N/Print >>", "endobj"); + }); + + this.internal.events.subscribe("putCatalog", function () { + this.internal.write("/OpenAction " + refAutoPrintTag + " 0" + " R"); + }); + return this; + }; +})(jsPDF.API); + +/** + * jsPDF Canvas PlugIn + * Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. + * http://opensource.org/licenses/mit-license + */ + +/** + * This plugin mimics the HTML5 Canvas + * + * The goal is to provide a way for current canvas users to print directly to a PDF. + */ + +(function (jsPDFAPI) { + 'use strict'; + + jsPDFAPI.events.push(['initialized', function () { + this.canvas.pdf = this; + }]); + + jsPDFAPI.canvas = { + getContext: function getContext(name) { + this.pdf.context2d._canvas = this; + return this.pdf.context2d; + }, + style: {} + }; + + Object.defineProperty(jsPDFAPI.canvas, 'width', { + get: function get() { + return this._width; + }, + set: function set(value) { + this._width = value; + this.getContext('2d').pageWrapX = value + 1; + } + }); + + Object.defineProperty(jsPDFAPI.canvas, 'height', { + get: function get() { + return this._height; + }, + set: function set(value) { + this._height = value; + this.getContext('2d').pageWrapY = value + 1; + } + }); + + return this; +})(jsPDF.API); + +/** ==================================================================== + * jsPDF Cell plugin + * Copyright (c) 2013 Youssef Beddad, youssef.beddad@gmail.com + * 2013 Eduardo Menezes de Morais, eduardo.morais@usp.br + * 2013 Lee Driscoll, https://github.com/lsdriscoll + * 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria + * 2014 James Hall, james@parall.ax + * 2014 Diego Casorran, https://github.com/diegocr + * + * + * ==================================================================== + */ + +(function (jsPDFAPI) { + 'use strict'; + /*jslint browser:true */ + /*global document: false, jsPDF */ + + var fontName, + fontSize, + fontStyle, + padding = 3, + margin = 13, + headerFunction, + lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined }, + pages = 1, + setLastCellPosition = function setLastCellPosition(x, y, w, h, ln) { + lastCellPos = { 'x': x, 'y': y, 'w': w, 'h': h, 'ln': ln }; + }, + getLastCellPosition = function getLastCellPosition() { + return lastCellPos; + }, + NO_MARGINS = { left: 0, top: 0, bottom: 0 }; + + jsPDFAPI.setHeaderFunction = function (func) { + headerFunction = func; + }; + + jsPDFAPI.getTextDimensions = function (txt) { + fontName = this.internal.getFont().fontName; + fontSize = this.table_font_size || this.internal.getFontSize(); + fontStyle = this.internal.getFont().fontStyle; + // 1 pixel = 0.264583 mm and 1 mm = 72/25.4 point + var px2pt = 0.264583 * 72 / 25.4, + dimensions, + text; + + text = document.createElement('font'); + text.id = "jsPDFCell"; + + try { + text.style.fontStyle = fontStyle; + } catch (e) { + text.style.fontWeight = fontStyle; + } + + text.style.fontName = fontName; + text.style.fontSize = fontSize + 'pt'; + try { + text.textContent = txt; + } catch (e) { + text.innerText = txt; + } + + document.body.appendChild(text); + + dimensions = { w: (text.offsetWidth + 1) * px2pt, h: (text.offsetHeight + 1) * px2pt }; + + document.body.removeChild(text); + + return dimensions; + }; + + jsPDFAPI.cellAddPage = function () { + var margins = this.margins || NO_MARGINS; + + this.addPage(); + + setLastCellPosition(margins.left, margins.top, undefined, undefined); + //setLastCellPosition(undefined, undefined, undefined, undefined, undefined); + pages += 1; + }; + + jsPDFAPI.cellInitialize = function () { + lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined }; + pages = 1; + }; + + jsPDFAPI.cell = function (x, y, w, h, txt, ln, align) { + var curCell = getLastCellPosition(); + var pgAdded = false; + + // If this is not the first cell, we must change its position + if (curCell.ln !== undefined) { + if (curCell.ln === ln) { + //Same line + x = curCell.x + curCell.w; + y = curCell.y; + } else { + //New line + var margins = this.margins || NO_MARGINS; + if (curCell.y + curCell.h + h + margin >= this.internal.pageSize.height - margins.bottom) { + this.cellAddPage(); + pgAdded = true; + if (this.printHeaders && this.tableHeaderRow) { + this.printHeaderRow(ln, true); + } + } + //We ignore the passed y: the lines may have different heights + y = getLastCellPosition().y + getLastCellPosition().h; + if (pgAdded) y = margin + 10; + } + } + + if (txt[0] !== undefined) { + if (this.printingHeaderRow) { + this.rect(x, y, w, h, 'FD'); + } else { + this.rect(x, y, w, h); + } + if (align === 'right') { + if (!(txt instanceof Array)) { + txt = [txt]; + } + for (var i = 0; i < txt.length; i++) { + var currentLine = txt[i]; + var textSize = this.getStringUnitWidth(currentLine) * this.internal.getFontSize(); + this.text(currentLine, x + w - textSize - padding, y + this.internal.getLineHeight() * (i + 1)); + } + } else { + this.text(txt, x + padding, y + this.internal.getLineHeight()); + } + } + setLastCellPosition(x, y, w, h, ln); + return this; + }; + + /** + * Return the maximum value from an array + * @param array + * @param comparisonFn + * @returns {*} + */ + jsPDFAPI.arrayMax = function (array, comparisonFn) { + var max = array[0], + i, + ln, + item; + + for (i = 0, ln = array.length; i < ln; i += 1) { + item = array[i]; + + if (comparisonFn) { + if (comparisonFn(max, item) === -1) { + max = item; + } + } else { + if (item > max) { + max = item; + } + } + } + + return max; + }; + + /** + * Create a table from a set of data. + * @param {Integer} [x] : left-position for top-left corner of table + * @param {Integer} [y] top-position for top-left corner of table + * @param {Object[]} [data] As array of objects containing key-value pairs corresponding to a row of data. + * @param {String[]} [headers] Omit or null to auto-generate headers at a performance cost + * @param {Object} [config.printHeaders] True to print column headers at the top of every page + * @param {Object} [config.autoSize] True to dynamically set the column widths to match the widest cell value + * @param {Object} [config.margins] margin values for left, top, bottom, and width + * @param {Object} [config.fontSize] Integer fontSize to use (optional) + */ + + jsPDFAPI.table = function (x, y, data, headers, config) { + if (!data) { + throw 'No data for PDF table'; + } + + var headerNames = [], + headerPrompts = [], + header, + i, + ln, + cln, + columnMatrix = {}, + columnWidths = {}, + columnData, + column, + columnMinWidths = [], + j, + tableHeaderConfigs = [], + model, + jln, + func, + + + //set up defaults. If a value is provided in config, defaults will be overwritten: + autoSize = false, + printHeaders = true, + fontSize = 12, + margins = NO_MARGINS; + + margins.width = this.internal.pageSize.width; + + if (config) { + //override config defaults if the user has specified non-default behavior: + if (config.autoSize === true) { + autoSize = true; + } + if (config.printHeaders === false) { + printHeaders = false; + } + if (config.fontSize) { + fontSize = config.fontSize; + } + if (config.css && typeof config.css['font-size'] !== "undefined") { + fontSize = config.css['font-size'] * 16; + } + if (config.margins) { + margins = config.margins; + } + } + + /** + * @property {Number} lnMod + * Keep track of the current line number modifier used when creating cells + */ + this.lnMod = 0; + lastCellPos = { x: undefined, y: undefined, w: undefined, h: undefined, ln: undefined }, pages = 1; + + this.printHeaders = printHeaders; + this.margins = margins; + this.setFontSize(fontSize); + this.table_font_size = fontSize; + + // Set header values + if (headers === undefined || headers === null) { + // No headers defined so we derive from data + headerNames = Object.keys(data[0]); + } else if (headers[0] && typeof headers[0] !== 'string') { + var px2pt = 0.264583 * 72 / 25.4; + + // Split header configs into names and prompts + for (i = 0, ln = headers.length; i < ln; i += 1) { + header = headers[i]; + headerNames.push(header.name); + headerPrompts.push(header.prompt); + columnWidths[header.name] = header.width * px2pt; + } + } else { + headerNames = headers; + } + + if (autoSize) { + // Create a matrix of columns e.g., {column_title: [row1_Record, row2_Record]} + func = function func(rec) { + return rec[header]; + }; + + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + + columnMatrix[header] = data.map(func); + + // get header width + columnMinWidths.push(this.getTextDimensions(headerPrompts[i] || header).w); + column = columnMatrix[header]; + + // get cell widths + for (j = 0, cln = column.length; j < cln; j += 1) { + columnData = column[j]; + columnMinWidths.push(this.getTextDimensions(columnData).w); + } + + // get final column width + columnWidths[header] = jsPDFAPI.arrayMax(columnMinWidths); + + //have to reset + columnMinWidths = []; + } + } + + // -- Construct the table + + if (printHeaders) { + var lineHeight = this.calculateLineHeight(headerNames, columnWidths, headerPrompts.length ? headerPrompts : headerNames); + + // Construct the header row + for (i = 0, ln = headerNames.length; i < ln; i += 1) { + header = headerNames[i]; + tableHeaderConfigs.push([x, y, columnWidths[header], lineHeight, String(headerPrompts.length ? headerPrompts[i] : header)]); + } + + // Store the table header config + this.setTableHeaderRow(tableHeaderConfigs); + + // Print the header for the start of the table + this.printHeaderRow(1, false); + } + + // Construct the data rows + for (i = 0, ln = data.length; i < ln; i += 1) { + var lineHeight; + model = data[i]; + lineHeight = this.calculateLineHeight(headerNames, columnWidths, model); + + for (j = 0, jln = headerNames.length; j < jln; j += 1) { + header = headerNames[j]; + this.cell(x, y, columnWidths[header], lineHeight, model[header], i + 2, header.align); + } + } + this.lastCellPos = lastCellPos; + this.table_x = x; + this.table_y = y; + return this; + }; + /** + * Calculate the height for containing the highest column + * @param {String[]} headerNames is the header, used as keys to the data + * @param {Integer[]} columnWidths is size of each column + * @param {Object[]} model is the line of data we want to calculate the height of + */ + jsPDFAPI.calculateLineHeight = function (headerNames, columnWidths, model) { + var header, + lineHeight = 0; + for (var j = 0; j < headerNames.length; j++) { + header = headerNames[j]; + model[header] = this.splitTextToSize(String(model[header]), columnWidths[header] - padding); + var h = this.internal.getLineHeight() * model[header].length + padding; + if (h > lineHeight) lineHeight = h; + } + return lineHeight; + }; + + /** + * Store the config for outputting a table header + * @param {Object[]} config + * An array of cell configs that would define a header row: Each config matches the config used by jsPDFAPI.cell + * except the ln parameter is excluded + */ + jsPDFAPI.setTableHeaderRow = function (config) { + this.tableHeaderRow = config; + }; + + /** + * Output the store header row + * @param lineNumber The line number to output the header at + */ + jsPDFAPI.printHeaderRow = function (lineNumber, new_page) { + if (!this.tableHeaderRow) { + throw 'Property tableHeaderRow does not exist.'; + } + + var tableHeaderCell, tmpArray, i, ln; + + this.printingHeaderRow = true; + if (headerFunction !== undefined) { + var position = headerFunction(this, pages); + setLastCellPosition(position[0], position[1], position[2], position[3], -1); + } + this.setFontStyle('bold'); + var tempHeaderConf = []; + for (i = 0, ln = this.tableHeaderRow.length; i < ln; i += 1) { + this.setFillColor(200, 200, 200); + + tableHeaderCell = this.tableHeaderRow[i]; + if (new_page) { + this.margins.top = margin; + tableHeaderCell[1] = this.margins && this.margins.top || 0; + tempHeaderConf.push(tableHeaderCell); + } + tmpArray = [].concat(tableHeaderCell); + this.cell.apply(this, tmpArray.concat(lineNumber)); + } + if (tempHeaderConf.length > 0) { + this.setTableHeaderRow(tempHeaderConf); + } + this.setFontStyle('normal'); + this.printingHeaderRow = false; + }; +})(jsPDF.API); + +/** + * jsPDF Context2D PlugIn Copyright (c) 2014 Steven Spungin (TwelveTone LLC) steven@twelvetone.tv + * + * Licensed under the MIT License. http://opensource.org/licenses/mit-license + */ + +/** + * This plugin mimics the HTML5 Canvas's context2d. + * + * The goal is to provide a way for current canvas implementations to print directly to a PDF. + */ + +/** + * TODO implement stroke opacity (refactor from fill() method ) + * TODO transform angle and radii parameters + */ + +/** + * require('jspdf.js'); require('lib/css_colors.js'); + */ + +(function (jsPDFAPI) { + 'use strict'; + + jsPDFAPI.events.push(['initialized', function () { + this.context2d.pdf = this; + this.context2d.internal.pdf = this; + this.context2d.ctx = new context(); + this.context2d.ctxStack = []; + this.context2d.path = []; + }]); + + jsPDFAPI.context2d = { + pageWrapXEnabled: false, + pageWrapYEnabled: false, + pageWrapX: 9999999, + pageWrapY: 9999999, + ctx: new context(), + f2: function f2(number) { + return number.toFixed(2); + }, + + fillRect: function fillRect(x, y, w, h) { + if (this._isFillTransparent()) { + return; + } + x = this._wrapX(x); + y = this._wrapY(y); + + var xRect = this._matrix_map_rect(this.ctx._transform, { x: x, y: y, w: w, h: h }); + this.pdf.rect(xRect.x, xRect.y, xRect.w, xRect.h, "f"); + }, + + strokeRect: function strokeRect(x, y, w, h) { + if (this._isStrokeTransparent()) { + return; + } + x = this._wrapX(x); + y = this._wrapY(y); + + var xRect = this._matrix_map_rect(this.ctx._transform, { x: x, y: y, w: w, h: h }); + this.pdf.rect(xRect.x, xRect.y, xRect.w, xRect.h, "s"); + }, + + /** + * We cannot clear PDF commands that were already written to PDF, so we use white instead.