helpers/makePdfPreview.js

define(
    [
        'knockout',
        'pdfMake',
        'ko-mapping',
        'vfsfonts'
    ],
    function(ko, pdfMake, mapping) {
        function getNumberedFields(fields) {
            return ko.utils.arrayFilter(fields, function(field) {
                return field.showNumbering();
            });
        }
        /**
         * PDF preview maker used on report editor
         * For now the table of contents is only working on a single level template tree
         * @module app/helpers/makePDFPreview
         * @param  {Array} fields              Array of fields
         * @param  {Object} document_definition pdfMake config
         * @return {PDF}                     The created PDF
         * @requires knockout
         * @requires pdfMake
         * @requires ko-mapping
         * @requires vfsfonts
         */
        return function makePDF(fields, document_definition) {
            // get all the numbered fields in the template field tree
            var numbered_fields = getNumberedFields(fields);
            // Table of contents config
            var TOC = [{
                text: 'Table of Contents\n\n',
                alignment: 'center'
            }];
            // PDF header
            var header = null;
            
            var table_temp = [];
            
            var table_body_temp = [];
            ko.utils.arrayForEach(numbered_fields, function(numbered_field) {
                table_body_temp = [];
                header = {
                    text: numbered_field.formatted_numbering + (numbered_field.hint() || numbered_field.defaultText()),
                    style: 'header'
                };
                // For example purposes, this is fixed to the following value
                // @todo Add a way to customise this
                table_body_temp.push(['Numbering', 'Label', 'Value']);
                
                //Add items to the table of contents
                TOC.push(header, {
                    separator: ' ',
                    ol: ko.utils.arrayMap(numbered_field.childFields(), function(child_field) {
                        // console.log(mapping.toJS(child_field).read_only);
                        
                        //This is were the main PDF content is created
                        //1 page per template field
                        //I mixed it here on the arrayMapping but I will move it out in the future
                        if (child_field) {
                            var input = child_field.read_only() ? mapping.toJS(child_field.childFields())[0] : input = mapping.toJS(child_field);
                            var numbering = child_field.formatted_numbering || 'N/A';
                            var label = (child_field.hint() || child_field.defaultText());
                            var value = input && input.value || 'N/A';
                            
                            table_body_temp.push([
                                numbering,
                                label,
                                value
                            ]);

                        }

                        //The configuration if the child field is numbered
                        if (child_field.showNumbering()) {
                            return {
                                style: ['indent', 'italic'],
                                text: child_field.hint() || child_field.defaultText(),
                                counter: child_field.formatted_numbering
                            };
                        } else {
                            return {
                                type: 'none',
                                text: ''
                            };
                        }
                    })
                });
                table_temp.push({
                    text: header.text,
                    style: 'subheader'
                }, {
                    pageBreak: 'after',
                    widths: ['auto', 'auto', 'auto', 'auto'],
                    table: {
                        body: table_body_temp
                    }
                });
            });

            TOC.push({
                text: '',
                pageBreak: 'after'
            });

            document_definition.content = TOC.concat(table_temp);
            return pdfMake.createPdf(document_definition);
        }
    });