Name

global.GeneralPDF

Description

General Application Builds PDF preview and generates PDF document using GeneralForm2 as the HTML template

Script

/**
* Provides an API for dynamically building a PDF document. Can program the
* document global page properties i.e. header/footer, document dimensions, and
* add content generated by any compatible external source.
* 
* Uses com.itextpdf API Commands to create the PDF Document and content.
* 
*/
var GeneralPDF = Class.create();
GeneralPDF.LETTER = 'letter';
GeneralPDF.GENERAL_PDF_PAGE_SIZE = 'general.pdf.page.size';
GeneralPDF.A4 = 'a4';
GeneralPDF.ATTACHMENT_TYPE = 'application/pdf';
GeneralPDF.prototype = {
  initialize : function(pdfDoc, css, glideRecord) {
  	this.document = null;
  	this.savedDoc = null;
  	this.writer = null;
  	this.outputStream = new GeneralFormJava.ByteArrayOutputStream();
  	
  	this.footerImage = null;
  	this.headerImage = null;
  	this.footnote = null;
  	this.headerPosition = null;
  	this.footerPosition = null;
  	this.pageSize = null;
  	
  	this.pdfDoc = null;
  	this.glideRecord = null;
  	this.htmlWorker = null;
  	this.styles = null;
  	this.pdfElements = [];

  	//if (glideRecord) {
  	//	this.glideRecord = glideRecord;
  	//}

  	if (pdfDoc) {
  		this._loadPDFDoc(pdfDoc);
  	}

  	// if (css) {
  	// this._loadStyles(css);
  	// }

  	// this.page = 1;
  	this.total = null;
  	this.BaseFnt = new iTextPDFUtil().getFont();
  },
  
  setDocTempleInfo : function(headerImage, footerImage, footnote, headerPosition, footerPosition, pageSize){
  	this.headerImage = headerImage;
  	this.footerImage = footerImage;
  	this.footnote = footnote;
  	this.headerPosition = headerPosition;
  	this.footerPosition = footerPosition;
  	this.pageSize = pageSize;
  	
  },	
  

  _loadPDFDoc : function(pdfDoc) {
  	this.pdfDoc = pdfDoc;
  	
  	// this.document is used here to create a write in _connectOutputStream()
  	// then, this.cocument will be reassigned to GeneralPDF
  	this.document = this.pdfDoc.get(); 		
  	this.savedDoc = this.document;
  	this._connectOutputStream();
  },
  
  _loadStyles : function(css1) {

  	/**
  	 * Unsupported Styles
  	 * 
  	 */
  	// this.styles.loadStyle('value_col_annotation', 'display', 'none');
  	// this.styles.loadStyle('value_col_annotation', 'visibility',
  	// 'hidden');
  	// this.styles.loadTagStyle('td', 'background-color', 'blue;');
  	// this.styles.loadStyle('label_col', 'width', '50px');
  	/**
  	 * this.styles.loadStyle('label_col', 'color', 'green'); // Load from
  	 * sheet // TODO: testing var css2 = new SSAQuoteCSS().get();
  	 * 
  	 * for ( var className in css2) { if (css2.hasOwnProperty(className)) {
  	 * gs.print(className); var styles = css2[className]; for ( var style in
  	 * styles) { if (styles.hasOwnProperty(style)) {
  	 * 
  	 * 
  	 * gs.print('Loading className ' + className + ' , Style Attribute '
  	 * +style + ' , Style ' + styles[style] + '\n');
  	 * 
  	 * this.styles.loadStyle(className, style, styles[style]); } } } }
  	 */

  },

  /**
   * Dynamically program PDF content
   */
  _generate : function() {
  	// Open the document for writing
  	this.document.open();
  	
  	// Write to the document
  	this.document.add(this.pdfDoc.body);

  	// Close the document
  	this.document.close();
  	this.writer.close();
  },

  /**
   * This will open the document for writing and run anything we need for the
   * stream writer or the iTextPDF API. All of this runs and is prepared
   * before any kind of HTML form generation takes place at all. This will
   * specifically prepare GeneralPDF for a certain kind of HTML parsing when
   * generating the HTML. Which is to parse GeneralFormElement(s) one at a time.
   * This creates an API for changing the stream writer or iTextPDF API based
   * on GeneralElement types.
   * 
   * 
   */
  startHTMLParser : function() {
  	this._loadStyles();

  	// setValue method on PDFTemplate may be used to add any property
  	// to the template that can then be read by the header, footer,
  	// watermark, etc.
  	if (this.glideRecord) {
  		this.PDFTemplate.setValue('glideRecord' , this.glideRecord);
  	}

  	this.writer.setPageEvent(this.headerImage, this.footerImage, this.footnote, this.headerPosition, this.footerPosition, this.pageSize);

  	// Add any viewer preferences
  	//
  	// Set the Print Scaling
  	var PdfName = iTextPDFUtil.PdfName;
  	var pn = new PdfName();
  	var PRINTSCALING = pn.getPdfName('PRINTSCALING');
  	var NONE = pn.getPdfName('NONE');
  	this.writer.addViewerPreference(PRINTSCALING, NONE);

  	// Open document for writing
  	this.document.open();

  	// Since this is for parsing it should not be initialized as part
  	// of creating a GeneralPDF. Inside this _parse() method is a good
  	this.htmlWorker = new iTextPDFUtil.HTMLWorker(this.document);

  	// Use style sheet
  	//this.htmlWorker.setStyleSheet(this.styles);     
  	//this.htmlWorker.setStyleSheet(["font-family: journal, Times", "border-color:blue", "color:red", "width:100%"]);     		

  	// Basically at this point in the form generation process we use
  	// this.addHTML() while iterating over GeneralFormElement(s) within
  	// GeneralFormTable.
  	// Then we just stop the parser with stopHTMLParser() and use get() to
  	// retrieve the final PDF file ready to be attached or download
  },

  stopHTMLParser : function() {

  	// Add all of the elements that have been collected to the document.  The pdfElements is null
// 		for ( var i = 0; i < this.pdfElements.length; i += 1) {
// 			var element = this.pdfElements[i];
// 			this.document.add(element);
// 		}

  	this.document.close();
  	this.writer.close();
  },

  /**
   * Automate PDF generation by parsing HTML/CSS
   */
  /*
  _parse : function() {
  	var isValid = new GeneralFormJava.GlideXMLUtil()
  			.isValidHTML(this.pdfDoc.html);

  	if (!isValid) {
  		// this.writer.close();

  		gs.print('HTML is not valid');

  		// return;
  	} else {
  		gs.print('HTML is valid');

  		// We had to escape the HTML from the WYSIWYG elements to render in
  		// the UI Page.
  		// Undo that here so we get the proper render in the PDF.
  		// TODO: Use the DOM to target just elements that can have escaped
  		// data
  		this.pdfDoc.html = GeneralForm2.getStringUtil().unEscapeHTML(
  				this.pdfDoc.html);

  		gs.print(this.pdfDoc.html);
  	}

  	try {
  		this._loadStyles();

  		// Use a template for the page event
  		//this.writer.setPageEvent(this.PDFTemplate);

  		// Add any viewer preferences
  		//
  		// Set the Print Scaling
  		var PdfName = iTextPDFUtil.PdfName;
  		var pn = new PdfName();
  		this.writer.addViewerPreference(pn.getPdfName('PRINTSCALING'), pn.getPdfName('NONE'));

  		// Open document for writing
  		this.document.open();

  		// Start writing content to the document
  		var contentReader = new GeneralFormJava.StringReader(
  				this.pdfDoc.html + '');

  		// Since this is for parsing it should not be initialized as part
  		// of creating a GeneralPDF. Inside this _parse() method is a good
  		this.htmlWorker = new iTextPDFUtil.HTMLWorker(this.document);

  		// Use style sheet
  		// htmlWorker.setStyleSheet(this.styles);

  		// Parse 1
  		this.htmlWorker.parse(contentReader);

  		// parse 2
  		// this.addHTML(this.pdfDoc.html);

  		this.document.close();
  		this.writer.close();

  	} catch (e) {
  		gs.print('Failed to created PDF Document. Exception: ' + e);
  		return;
  	}
  },
  */

  /**
   * This is used to add blocks of HTML anywhere in a PDF document object
   * 
   * @param html
   */
  addHTML : function(html) {

  	var isValid = new GeneralFormJava.GlideXMLUtil().isValidHTML(html);

  	if (!isValid) {
  		// this.writer.close();

  		this.debug.log('HTML is not valid');

  		// return;
  	} else {
  		this.debug.log('HTML is valid');

  		// We had to escape the HTML from the WYSIWYG elements to render in
  		// the UI Page.
  		// Undo that here so we get the proper render in the PDF.
  		// TODO: Use the DOM to target just elements that can have escaped
  		// data
  		
  		// html = GeneralForm2.getStringUtil().unEscapeHTML(html);
  		html = GeneralFormJava.GlideStringUtil.unEscapeHTML(html);
  	
  	}

  	try {
  		var contentReader = new GeneralFormJava.StringReader(html + '');
  		
  		// Use style sheet
  		//this.htmlWorker.setStyleSheet(this.styles);

  		// Parse 1
  	    //this.htmlWorker.parse(contentReader);

  		var objects = this.htmlWorker.parseToList(contentReader);
  		
  		for ( var i = 0; i < objects.size(); i += 1) {
  			var element = objects.get(i);
  			this.document.addParagraph(element, this.BaseFnt);
  		}

  	} catch (e) {
  		this.debug.log('Failed to created PDF Document. Exception: ' + e);
  		this.debug.write();
  		return;
  	}
  },

  addNewPage: function(){
  	this.document.addNewPage();
  },

  addCells: function(cells, row_length){
  	var table = new iTextPDFUtil.PDFTable(row_length);
  	table.setWidthPercentage(100);
  	table.setBorderWidth(0);
  	table.setPadding(0);
  	table.setSpacing(0);
  	for(var i=0;i<cells.length;i++){
  		var row = parseInt(i/row_length);
  		var font = new iTextPDFUtil().getFont(null, (row == 0) ? 1 :null,(cells[i].color)? new iTextPDFUtil.Color((cells[i].color == 'text-success') ? 0xFF5CB85C: 0xFFD9534F) : null, null);
  		var pdfCell = new iTextPDFUtil.PDFCell(new iTextPDFUtil.PDFPhrase(cells[i].text, font));
  		if(row%2 == 0)
  			pdfCell.setBackgroundColor();
  		pdfCell.setCellProperties();
  		table.addCell(pdfCell);
  	}
  	this.document.add(table);
  },

  addSVG: function(svg, position){
  	svg = svg.replaceAll("[^\\x20-\\x7e]", "");
  	new iTextPDFUtil.SvgToPdf().createPdf(this.writer, this.document, svg, position);
  },

  _connectOutputStream : function() {
  	try {

  		//this.writer = iTextPDFUtil.PdfWriter.getInstance(this.document, this.outputStream);
  		this.writer = new iTextPDFUtil.PdfWriter(this.document, this.outputStream);

  		this.writer.setStrictImageSequence(true);
  		
  	} catch (e) {
  		gs.log(e, 'DocumentException');
  	}
  },

  _properties : function(document) {
  	document.addAuthor('');
  	document.addCreationDate();
  	document.addProducer();
  	document.addCreator('');
  	document.addTitle('');
  },

  _header : function(document) {
  	// TODO: Simple example
  },

  setPDFDoc : function(pdfDoc) {
  	this._loadPDFDoc(pdfDoc);
  },

  setProperties : function(properties) {
  	this._properties = properties;
  },

  setHeader : function(header) {
  	//GeneralPDF.prototype._header.apply(this, [this.writer, this.document]);

  },

  setFooter : function(footer) {
  	//GeneralPDF.prototype._footer.apply(this, [this.writer, this.document]);
  },
  
  setWatermark : function(watermark) {
  	GeneralPDF.prototype._watermark = watermark;
  },

  /**
   * Returns the input stream from the output document.
   * 
   * @returns {ByteArrayInputStream}
   */
  get : function() {
  	var ret = null;

  	if (this.document) {

  		/**
  		 * if (this.pdfDoc.html) { this._parse(); } else if
  		 * (this.pdfDoc.body) { this._generate(); }
  		 */

  		ret = new GeneralFormJava.ByteArrayInputStream(this.outputStream
  				.toByteArray());
  	}

  	return ret;
  },

  type : 'GeneralPDF'
};

/**
* Commit the generated PDF document as an attachment in the database
* @param {GeneralPDF.Attachment}
* sa @ return {String} sys_id for the newly created attachment
*/
GeneralPDF.attach = function(sa) {
  var SysAttachment = new GeneralFormJava.SysAttachment();
  var type = GeneralPDF.ATTACHMENT_TYPE;
  if (sa.type) {
  	type = sa.type;
  }
  
  var aId = SysAttachment.write(sa.tableId, sa.tableName, sa.name, type, sa.body);
  return aId + '';
};

/**
* Interface for an attachment file.
* @param tableId
* @param tableName
* @param name
* @param body
* @param type
*/
GeneralPDF.Attachment = function(tableId, tableName, name, body, type) {
  this.tableId = '';
  this.tableName = '';
  this.name = '';
  this.type = null;
  this.body = null;
  this.html = null;

  this.setTableId = function(ti) {
  	this.tableId = ti;
  };
  this.setTableName = function(tn) {
  	this.tableName = tn;
  };
  this.setName = function(na) {
  	this.name = na;
  };
  this.setType = function(ty) {
  	this.type = ty;
  };
  this.setBody = function(bo) {
  	this.body = bo;
  };

  if (tableId) {
  	this.setTableId(tableId);
  }
  if (tableName) {
  	this.setTableName(tableName);
  }
  if (name) {
  	this.setName(name);
  }
  if (type) {
  	this.setType(type);
  }
  if (body) {
  	this.setBody(body);
  }
};

/**
* Create a PDF Document object set the body/content page orientation and
* margins for the document.
* @param landscape
* @param meta
* @param body
*/
GeneralPDF.Document = function(landscape, meta, body, html, pageSize, headerImage) {

  var ps = new iTextPDFUtil.PageSize();
  
  this.rectangle = ps.getPageSize(pageSize);
  
  this.landscape = false;
  
  var leftMargin = 72;
  var rightMargin = 72;
  var topMargin = 36;
  var bottomMargin = 36;
  var headerImageHeight = 50;

  // This is the default body that just ensures we do get a complete PDF
  // Document
  // if you call this object and do nothing to it. Setting the actual body
  // content
  // is the responsibility of the caller.
  // this inline function won't be executed
  this.body = function(document) {
  	if (document.isNil()){
  		gs.logError('GeneralPDF() Input parameter "document" should not be null.');
  	}		
  	var table = new iTextPDFUtil.PDFTable(1);
  	table.setBorderWidth(0);
  	table.setPadding(0);
  	table.setSpacing(0);
  	table.addCell("All systems are a go! Default body, Replace Me");
  	document.add(table);
  };

  //this.html;

  this.setLandscape = function(la) {
  	this.landscape = la;
  };

  this.setBody = function(bo) {
  	this.body = bo;
  };

  this.setHTML = function(html) {
  	this.html = html;
  };

  if (landscape) {
  	this.setLandscape(landscape);
  }

  if (body) {
  	this.setBody(body);
  }

  if (html) {
  	this.setHTML(html);
  }

  this.get = function() {
  	var ret = null;

  	if (headerImage) {
  		ret = new iTextPDFUtil.Document(this.rectangle, leftMargin, rightMargin, topMargin + headerImageHeight, bottomMargin); 			
  	} else {
  		
  		ret = new iTextPDFUtil.Document(this.rectangle, leftMargin, rightMargin, topMargin, bottomMargin); 
  	}

  	return ret;
  };

  this.type = 'GeneralPDF.Document';
};

Sys ID

dcc5ee1137102100904961d8bcbe5d6d

Offical Documentation

Official Docs: