Skip to content

Commit

Permalink
Issue #29 - Generating a PDF
Browse files Browse the repository at this point in the history
First steps in PDF generation are OK !
Added pdfMake library
Current cards added to a PDF
Still needs to manage the width / height of cards, and the layout
  • Loading branch information
Gulix committed Jul 2, 2017
1 parent 6f3f3f6 commit b77a710
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 37 deletions.
27 changes: 22 additions & 5 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ <h3><span class="icon icon-save"></span> Load / Save your cards</h3>
</select>
<label>Create a deck named</label>
<div class="modal-buttons">
<input type="text" class="input-text" data-bind="value: newDeckName"></input>
<input type="text" class="input-text" data-bind="value: newDeckName"></input>
<a class="btn primary blue iconized icon-add" data-bind="click: saveCurrentDeckAsNew">New</a>
</div>
<div class="modal-buttons">
Expand Down Expand Up @@ -305,6 +305,21 @@ <h3 data-bind="visible: exportVM.exportActive">Export in Progress ...</h3>
</div>
</div>

<div style="display:none;" class="modal-box" data-bind="visible: pdfGenerator.isModalDisplayed">
<!-- ko with: pdfGenerator -->
<div class="modal-box-content">
<h3>Generate a PDF with all the cards</h3>
<div data-bind="visible: exportInactive">It will take approximatively <span data-bind="text: estimatedTime"></span> to complete.</div>
<h3 data-bind="visible: exportActive">Export in Progress ...</h3>
<div data-bind="visible: exportActive, progressBar: { value : progressPercentage }"></div>
<div class="modal-buttons">
<a class="btn primary mainColor2 iconized icon-file-zip" data-bind="visible: exportInactive, click: launchPdfGeneration">Generate the PDF</a>
<a class="btn secondary iconized icon-dismiss" data-bind="visible: exportInactive, click: cancel">Cancel</a>
</div>
</div>
<!-- /ko -->
</div>

</div>
</div>
</div>
Expand All @@ -321,11 +336,13 @@ <h3 data-bind="visible: exportVM.exportActive">Export in Progress ...</h3>
data-bind="click: menu.toggleCardExport, css: { 'sub-menu-opener': menu.isCardExportHidden, 'sub-menu-closer': menu.isCardExportDisplayed}"><span>export Card(s)</span></a>
<div class="sub-menu-list" data-bind="slideRightMenu: menu.isCardExportDisplayed">
<div class="sub-menu"><a href="#" class="icon-image" title="Export the card to a PNG image"
data-bind="click: exportVM.exportAsPNG"><span>to PNG</span></a></div>
data-bind="click: exportVM.exportAsPNG"><span>to PNG</span></a></div>
<div class="sub-menu"><a href="#" class="icon-file-svg" title="Export the card to a SVG image"
data-bind="click: exportVM.exportAsSVG"><span>to SVG</span></a></div>
<div class="sub-menu"><a href="#" class="icon-file-zip" title="Export all the card to a ZIP file"
data-bind="click: exportVM.exportAllToZip"><span>to Zip</span></a></div>
data-bind="click: exportVM.exportAsSVG"><span>to SVG</span></a></div>
<div class="sub-menu"><a href="#" class="icon-file-zip" title="Export all the cards to a ZIP file"
data-bind="click: exportVM.exportAllToZip"><span>to Zip</span></a></div>
<div class="sub-menu"><a href="#" class="icon-file-zip" title="Export all the cards to a PDF file"
data-bind="click: pdfGenerator.showPdfModal"><span>to PDF</span></a></div>
</div>
</li>
</ul>
Expand Down
13 changes: 12 additions & 1 deletion src/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,22 @@ require.config({
'cropper': 'vendor/cropper',
'webfont': 'vendor/webfont',
'jszip': 'vendor/jszip.min',
'moment': 'vendor/moment.min'
'moment': 'vendor/moment.min',
'pdfmake': 'vendor/vfs_fonts',
'pdfMakeLib': 'vendor/pdfmake.min'
},
shim: {
'jQuery': {
exports: '$'
},
pdfMakeLib :
{
exports: 'pdfMake'
},
pdfmake :
{
deps: ['pdfMakeLib'],
exports: 'pdfMake'
}
}
});
Expand Down
31 changes: 31 additions & 0 deletions src/js/vendor/pdfmake.min.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions src/js/vendor/vfs_fonts.js

Large diffs are not rendered by default.

31 changes: 3 additions & 28 deletions src/js/viewModels/engineVM.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ define(['knockout',
'viewModels/menuManager',
'viewModels/datastorage/loadsaveVM',
'viewModels/messagebar',
'viewModels/pdfGenerator',
'FileSaver'
], function(ko, fabric, FieldFactory, CardTemplateVM, UITemplates, Export, MenuManager, LoadSaveVM, MessageBar) {
], function(ko, fabric, FieldFactory, CardTemplateVM, UITemplates, Export, MenuManager, LoadSaveVM, MessageBar, PdfGenerator) {

/***************************************/
/* Main entry point of the application */
Expand All @@ -26,6 +27,7 @@ define(['knockout',
self.loadsaveVM = LoadSaveVM.getVM(self);
self.menu = MenuManager.newMenuManager();
self.generalMessageBar = MessageBar.getMessageBar();
self.pdfGenerator = PdfGenerator.getPdfGenerator(self);

self.isCardSelected = ko.pureComputed(function() {
return self.editableCard() != null;
Expand Down Expand Up @@ -171,40 +173,13 @@ define(['knockout',
}
}

/* Save / Load from localStorage */
/*self.saveFromLocalStorage = function() {
var jsonData = self.getListOfCardsAsJson();
DataStorage.saveCurrentList(jsonData);
alert("Save is done in localStorage");
}
self.loadFromLocalStorage = function() {
var cardsList = DataStorage.getList(1);
var cards = [ ];
if ((cardsList == null) || (cardsList.cardsData == null) || (cardsList.cardsData.constructor !== Array)) {
alert("Nothing retrieved from the localStorage");
} else {
cards = cardsList.cardsData;
}
self.importList(cards);
}*/

/*******************************/
/*End of Functions declaration */
/*******************************/

/* Initialization of the FabricJS canvas object */
self.canvas = new fabric.StaticCanvas('fabricjs-canvas');

/* Initialization of the Card Template */
//var cardTemplateVM = CardTemplateVM.newCardTemplateVM(jsonTemplate, self.updateCanvasSize, self.updateCardsFields);
//self.cardTemplate(cardTemplateVM);
//self.updateCanvasSize();

/* Initializing the list with one item */
//self.listCards().push(self.createNewCard());
//self.editableCard(self.listCards()[0]);

/* Initializing the UI parts */
self.UItemplates(UITemplates.getUItemplates(self));

Expand Down
3 changes: 0 additions & 3 deletions src/js/viewModels/exportVM.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ define(['jszip',
/********************************/
/* End of Variables declaration */
/********************************/
self.progress = ko.pureComputed(function() {
return self.indexCurrentExportedFile() + " / " + self.totalExportedFiles();
});
self.progressPercentage = ko.pureComputed(function() {
var val100 = 100 * self.indexCurrentExportedFile() / self.totalExportedFiles();
if (!Number.isInteger(val100)) {
Expand Down
110 changes: 110 additions & 0 deletions src/js/viewModels/pdfGenerator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
define(['knockout', 'pdfmake'], function(ko, pdfMake) {

/***********************************************************************/
/* ViewModel for Exporting the Cards (unique or list, svg or png, ...) */
/***********************************************************************/
function pdfGenerator(engineVM) {
var self = this;

/*************************/
/* Variables declaration */
/*************************/
self.mainEngineVM = engineVM;

// Displaying the Modal Export Frame
self.isModalDisplayed = ko.observable(false);
self.indexCurrentExportedFile = ko.observable(-1);
self.totalExportedFiles = ko.observable(-1);

// Export currently in progress
self.isExportInProgress = ko.observable(false);

// Construction of PDF
self.listDataUrls = [];

/********************************/
/* End of Variables declaration */
/********************************/
self.progressPercentage = ko.pureComputed(function() {
var val100 = 100 * self.indexCurrentExportedFile() / self.totalExportedFiles();
if (!Number.isInteger(val100)) {
return val100.toFixed(2)
}
return val100;
});

self.exportActive = ko.computed(function() { return self.isExportInProgress(); });
self.exportInactive = ko.computed(function() { return !self.isExportInProgress(); });
self.estimatedTime = ko.computed(function() {
return (self.mainEngineVM.listCards().length * 0.5) + "s";
});

/*************************/
/* Functions declaration */
/*************************/
// Opens the Modal Box for Zip Generation
self.showPdfModal = function() {
self.mainEngineVM.menu.hideCardExport();
self.isModalDisplayed(true);
self.indexCurrentExportedFile(0);
self.totalExportedFiles(self.mainEngineVM.listCards().length);
self.isExportInProgress(false);
self.listDataUrls = [];
}
self.cancel = function() {
self.isModalDisplayed(false);
}

self.launchPdfGeneration = function() {
self.isExportInProgress(true);
self.exportSingleCardToDataUrl(0);
}

self.exportSingleCardToDataUrl = function(iCardIndex) {
if ((iCardIndex >= 0) && (iCardIndex < self.mainEngineVM.listCards().length)) {

self.indexCurrentExportedFile(iCardIndex);
self.mainEngineVM.editableCard(self.mainEngineVM.listCards()[iCardIndex]);

// Timeout is needed in order to ensure the canvas is fully loaded
setTimeout(function() {
self.cardToDataUrl();
self.addDataUrlToList(iCardIndex);
}, 500); // TODO - Need to find a better way to launch action when the canvas is ready
} else if (iCardIndex >= self.mainEngineVM.listCards().length) {
self.indexCurrentExportedFile(iCardIndex);
self.integratesCardsIntoPdf();
}
}

self.integratesCardsIntoPdf = function() {
var docDef = { content: [] };
_.forEach(self.listDataUrls, function(dataUrl) {
docDef.content.push({ image: dataUrl, width: 250 });
})
pdfMake.createPdf(docDef).download();
self.cancel();
}

self.cardToDataUrl = function() {
if (self.mainEngineVM.editableCard() != null) {
//var canvas = document.getElementById('fabricjs-canvas');
var dataUrl = self.mainEngineVM.canvas.toDataURL({ format: 'png' });
self.listDataUrls.push(dataUrl);
}
}

self.addDataUrlToList = function(iCardIndex) {
self.exportSingleCardToDataUrl(iCardIndex + 1);
};

/*******************************/
/*End of Functions declaration */
/*******************************/
}
return {
getPdfGenerator: function(engineVM) {
return new pdfGenerator(engineVM);
}
}
});

0 comments on commit b77a710

Please sign in to comment.