Skip to content

Commit c79b72c

Browse files
author
Basic Primitives
committed
Reworked PDFkit samples
1 parent 2a6f708 commit c79b72c

38 files changed

+8217
-6366
lines changed

howtouse.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* [React Demos](https://github.com/BasicPrimitives/react-demo)
1111
* [AngularJS Organizational Chart Directive](/samples/AngularJSFirstOrganizationalChartDirective.md)
1212
* [jQuery Specific Use Cases](/samples/jQuerySpecific.md)
13+
* [PDFkit Specific Use Cases](/samples/PDFkitSpecific.md)
1314

1415
## User Interface Events & Options
1516
* [Selecting cursor item & Mouse click](/samples/SelectingCursorItem.md)

index.html

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@
1414
<link href="min/primitives.latest.css?5100" media="screen" rel="stylesheet" type="text/css" />
1515

1616
<script>
17-
var frameworks = ["javascript", "jquery"];
17+
var frameworks = ["javascript", "jquery", "pdfkit"];
1818
var frameworksLabels = {
1919
"javascript": "JavaScript",
20-
"jquery": "jQuery"
20+
"jquery": "jQuery",
21+
"pdfkit": "PDFkit"
2122
};
2223
var preferedFramework = "javascript";
2324
var files = [
@@ -136,7 +137,7 @@
136137
{
137138
label: "Client side PDF Generation and Download Samples",
138139
frameworks: {
139-
javascript: "samples/pdfkit.plugins/DemoPDFKitPlugins.html"
140+
pdfkit: "samples/pdfkit.plugins/DemoPDFKitPlugins.html"
140141
}
141142
},
142143
{
@@ -147,21 +148,58 @@
147148
}
148149
]
149150
},
151+
{
152+
label: "PDFkit Specific Use Cases",
153+
items: [
154+
{
155+
label: "Page Size Organizational Chart",
156+
frameworks: {
157+
pdfkit: "samples/pdfkit.plugins/AutoSizeOrgDiagram.html"
158+
}
159+
},
160+
{
161+
label: "Page Size Family Diagram",
162+
frameworks: {
163+
pdfkit: "samples/pdfkit.plugins/AutoSizeFamDiagram.html"
164+
}
165+
},
166+
{
167+
label: "PDF File Download Sample",
168+
frameworks: {
169+
pdfkit: "samples/pdfkit.plugins/FileDownload.html"
170+
}
171+
},
172+
{
173+
label: "Multi-page Document Example",
174+
frameworks: {
175+
pdfkit: "samples/pdfkit.plugins/Multipage.html"
176+
}
177+
},
178+
{
179+
label: "User Item Template with custom graphics",
180+
frameworks: {
181+
pdfkit: "samples/pdfkit.plugins/UserItemTemplateWithShapes.html"
182+
}
183+
}
184+
]
185+
},
150186
{
151187
label: "Create & Update use cases",
152188
items: [
153189
{
154190
label: "First Organizational Chart",
155191
frameworks: {
156192
javascript: "samples/javascript.controls/CaseFirstOrganizationalChart.html",
157-
jquery: "samples/jquery.widgets/CaseFirstOrganizationalChart.html"
193+
jquery: "samples/jquery.widgets/CaseFirstOrganizationalChart.html",
194+
pdfkit: "samples/pdfkit.plugins/FirstOrganizationalChart.html"
158195
}
159196
},
160197
{
161198
label: "First Family Chart",
162199
frameworks: {
163200
javascript: "samples/javascript.controls/CaseFirstFamilyChart.html",
164-
jquery: "samples/jquery.widgets/CaseFirstFamilyChart.html"
201+
jquery: "samples/jquery.widgets/CaseFirstFamilyChart.html",
202+
pdfkit: "samples/pdfkit.plugins/FirstFamilyChart.html"
165203
}
166204
},
167205
{
@@ -172,7 +210,7 @@
172210
}
173211
},
174212
{
175-
label: "Page Size Diagram",
213+
label: "Page Size Organizational Chart",
176214
frameworks: {
177215
javascript: "samples/javascript.controls/CasePageSizeDiagram.html",
178216
jquery: "samples/jquery.widgets/CasePageSizeDiagramWithoutUILayoutWidget.html"
@@ -337,7 +375,8 @@
337375
label: "Matrix Nodes layout in Family Chart",
338376
frameworks: {
339377
javascript: "samples/javascript.controls/CaseMatrixLayoutInFamilyChart.html",
340-
jquery: "samples/jquery.widgets/CaseMatrixLayoutInFamilyChart.html"
378+
jquery: "samples/jquery.widgets/CaseMatrixLayoutInFamilyChart.html",
379+
pdfkit: "samples/pdfkit.plugins/FamilyMatrix.html"
341380
}
342381
},
343382
{
@@ -350,7 +389,8 @@
350389
{
351390
label: "Nodes ordering",
352391
frameworks: {
353-
javascript: "samples/javascript.controls/CaseFamilyChartItemsOrdering.html"
392+
javascript: "samples/javascript.controls/CaseFamilyChartItemsOrdering.html",
393+
pdfkit: "samples/pdfkit.plugins/FamilyChartItemsOrdering.html"
354394
}
355395
},
356396
{
@@ -368,7 +408,8 @@
368408
label: "Item template",
369409
frameworks: {
370410
javascript: "samples/javascript.controls/CaseItemTemplate.html",
371-
jquery: "samples/jquery.widgets/CaseItemTemplate.html"
411+
jquery: "samples/jquery.widgets/CaseItemTemplate.html",
412+
pdfkit: "samples/pdfkit.plugins/UserItemTemplate.html"
372413
}
373414
},
374415
{
@@ -470,7 +511,8 @@
470511
{
471512
label: "Routing Highlight Path Annotation for hidden grand parents connections",
472513
frameworks: {
473-
javascript: "samples/javascript.controls/CaseFamilyHideGrandParentsConnections.html"
514+
javascript: "samples/javascript.controls/CaseFamilyHideGrandParentsConnections.html",
515+
pdfkit: "samples/pdfkit.plugins/HideGrandParentsConnectors.html"
474516
}
475517
}
476518
]

samples/FamilyConnectorsVisualization.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This is definitely extreme example of family relations, but the fact that famDia
1010
This visualization is better, but it shows another problem. The big number of parent and children elements does not let to see them together, so in order to make diagram more compact widget API supports clustering of nodes into matrix, so that way they occupy least space possible. In order to enable this layout option set `enableMatrixLayout` to `true`.
1111

1212
[JavaScript](javascript.controls/CaseFamilyChartMatrixLayout.html)
13+
[PDFKit](pdfkit.plugins/FamilyMatrix.html)
1314

1415
Another typical problem in connectors visualization is excessive grand parents relations. It is situation when item has direct relation to parent, grand parent and grand grand parent. Usually when we draw family diagram we are more interested to show order of dependencies over actual relations. We know that the great-grandparent precedes the grandparent, the grandparent precedes the parent, the parent precedes the child node. So this precedence defines the indirect relation between child node and grand-grandparent. So direct relation visualization between child node and its grand parents can be omitted out of diagram and replaced with dynamic annotations. Look at the following example where every child references all preceding parents:
1516

@@ -18,5 +19,6 @@ Another typical problem in connectors visualization is excessive grand parents r
1819
As you may see control already eliminated a lot of connections via making bundles, so we don't see every connection between nodes, but still this diagram has a lot of connections to trace. In order to hide direct connections to grand parents set option `hideGrandParentsConnectors` to `true` and get following layout:
1920

2021
[JavaScript](javascript.controls/CaseFamilyChartHiddenGrandParentsRelations.html)
22+
[PDFKit](pdfkit.plugins/HideGrandParentsConnectors.html)
2123

2224
So we got quite clean relations diagram between nodes. We still have all relations in place, the only difference is that grand parents connections go through actual parents, so we need to visualize them dynamically, as we navigate around our diagram we can highlight all current node immediate parents and children with Connector Path Annotations and set dynamically custom Item Template for them.

samples/FirstFamilyChart.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ The main difference of family diagram compared to organizational chart is suppor
1212
Family diagram provides some features specific to multi-parent layout, for example it supports in-layout "Labels cascades" over connections between parents and children.
1313

1414
[JavaScript](javascript.controls/CaseFirstFamilyChart.html)
15-
[JQuery](jquery.widgets/CaseFirstFamilyChart.html)
15+
[JQuery](jquery.widgets/CaseFirstFamilyChart.html)
16+
[PDFKit](pdfkit.plugins/FirstFamilyChart.html)

samples/FirstOrganizationalChart.md

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,94 @@ jQuery("#basicdiagram").orgDiagram({
119119
});
120120
```
121121

122+
## PDFKit
123+
124+
Basic Primitives library provides plugins for [PDFkit](www.PDFkit.org) (MIT License) - it is JavaScript PDF generation library for NodeJS and client side rendering in browser.
125+
126+
PDFKit library provides the most complete experience for rendering documents PDF format. Basic Primitves library implements additional plugins for PDFkit to render Diagrams on PDF page:
127+
* primitives.pdf.orgdiagram.Plugin - Organizational Chart PDFkit Plugin
128+
* primitives.pdf.famdiagram.Plugin - Family Diagram PDFkit Plugin
129+
130+
Basically PDFkit Plugins are stand alone products, they share many API options with Basic Primitives Controls, but they are completly deprived of interactivity and their rendering engine uses regular vector graphics and text elements of PDFkit libarary API, see PDFkit site for reference.
131+
132+
The following example is minimal code needed to create new empty PDF file on client side in browser using PDFkit library
133+
134+
```JavaScript
135+
const PDFDocument = require('pdfkit');
136+
const blobStream = require('blob-stream');
137+
138+
// create a document the same way as above
139+
const doc = new PDFDocument;
140+
141+
// pipe the document to a blob
142+
const stream = doc.pipe(blobStream());
143+
144+
// add your content to the document here, as usual
145+
146+
// get a blob when you're done
147+
doc.end();
148+
stream.on('finish', function() {
149+
// get a blob you can do whatever you like with
150+
const blob = stream.toBlob('application/pdf');
151+
152+
// or get a blob URL for display in the browser
153+
const url = stream.toBlobURL('application/pdf');
154+
iframe.src = url;
155+
});
156+
```
157+
158+
Basic Primitives Organizational Chart PDFkit plugin is just a rendering function, which renders diagram using PDFkit API methods:
159+
160+
``` JavaScript
161+
var firstOrganizationalChartSample = primitives.pdf.orgdiagram.Plugin({
162+
items: [
163+
new primitives.orgdiagram.ItemConfig({
164+
id: 0,
165+
parent: null,
166+
title: "Scott Aasrud",
167+
description: "VP, Public Sector",
168+
image: photos.a
169+
}),
170+
new primitives.orgdiagram.ItemConfig({
171+
id: 1,
172+
parent: 0,
173+
title: "Ted Lucas",
174+
description: "VP, Human Resources",
175+
image: photos.b
176+
}),
177+
new primitives.orgdiagram.ItemConfig({
178+
id: 2,
179+
parent: 0,
180+
title: "Joao Stuger",
181+
description: "Business Solutions, US",
182+
image: photos.c
183+
})
184+
],
185+
cursorItem: null,
186+
hasSelectorCheckbox: primitives.common.Enabled.False
187+
});
188+
189+
var size = firstOrganizationalChartSample.draw(doc, 100, 150);
190+
```
191+
192+
Pay attention that `draw` method returns actual `size` of the rendered diagram. It is needed to calculate offset in order to place other elements of PDF document underneath of it.
193+
194+
PDF document is very easy to scale to make it fit to paper size or split it into multiple pages. So we don't need to make PDF page fit into some fixed predefined paper size, but in order to avoid diagram being cut by PDF page boundaries we have to measure its size first and then create PDF page of approapriate size.
195+
196+
```JavaScript
197+
var sampleSize = samfirstOrganizationalChartSampleple3.getSize();
198+
```
199+
200+
`getSize` method returns diagram size, so we can create new PDF document big enough to accomodate our diagram:
201+
202+
```JavaScript
203+
var doc = new PDFDocument({ size: [sampleSize.width + 100, sampleSize.height + 150] });
204+
```
205+
206+
Plugin draws diagram in current PDFkit document layout transformation context, so developer can rotate, translate and scale diagrams on PDFkit document page.
207+
208+
Plugins are part of the Basic Primitives distribution assembly
209+
122210
[JavaScript](javascript.controls/CaseFirstOrganizationalChart.html)
123-
[JQuery](jquery.widgets/CaseFirstOrganizationalChart.html)
211+
[JQuery](jquery.widgets/CaseFirstOrganizationalChart.html)
212+
[PDFKit](pdfkit.plugins/FirstOrganizationalChart.html)

samples/ItemTemplates.md

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ result.itemTemplate = ["div",
6363
```
6464

6565
## Configuration Classes
66-
When we define node templates we can define Content Template, Cursor Template and Highlight Templates in one configuration object. This make sense since if we decide to customize cursor or highlight templates most likely we are going to make them item template specific. At the same time control does not require all 3 of them to be defined. If cursor or highlight templates properties are not set in template configuration object then control uses internal default template for all of them them. Generally all 3 templates can be set to null, so default templates are gonna be used by control. See template configuration properties in the following classes:
66+
When we define node templates we can define Content Template, Cursor Template and Highlight Templates in one configuration object. This make sense since if we decide to customize cursor or highlight templates most likely we are going to make them item template specific. At the same time control does not require all 3 of them to be defined. If cursor or highlight templates properties are not set in template configuration object then control uses internal default template for all of them. Generally all 3 templates can be set to null, so default templates are going to be used by control. See template configuration properties in the following classes:
6767

6868
* `primitives.orgdiagram.ItemConfig`
6969
* `primitives.famdiagram.Config`
@@ -120,15 +120,90 @@ Every template configuration object has name property, it is being used to refer
120120

121121
See following example of templates usage:
122122

123+
## PDF Templates
124+
125+
PDFKit Plugins use the same template objects with one major exception. All rendering is done using PDFKit API:
126+
127+
* [Text](http://pdfkit.org/docs/text.html)
128+
* [Images](http://pdfkit.org/docs/images.html)
129+
* [Vector Graphics](http://pdfkit.org/docs/vector.html)
130+
131+
See [PDFKit](http://pdfkit.org/) site for more details.
132+
133+
Basic Primitives PDFkit Plugins have no HTML or browsers specific dependencies, they share API options with their complimentary UI controls. The major API difference is that they have no UI events and rendering mechanism refit to use PDFkit document API methods. The following sample shows usage of `onTemplateRender` event handler, which receives `doc` reference to PDFkit `PDFDocument` instance and node `position` in PDF document coordinates:
134+
135+
Basically developer is free to render any content in node's position, the following sample renders frame, photo, title and PDF specific link annotation, which is clickable in PDF.
136+
137+
```JavaScript
138+
function onTemplateRender(doc, position, data) {
139+
var itemConfig = data.context;
140+
141+
if (data.templateName == "contactTemplate") {
142+
var contentSize = new primitives.common.Size(220, 108);
143+
144+
contentSize.width -= 2;
145+
contentSize.height -= 2;
146+
147+
doc.save();
148+
149+
/* item border */
150+
doc.roundedRect(position.x, position.y, position.width, position.height, 0)
151+
.lineWidth(1)
152+
.stroke('#dddddd');
153+
154+
/* photo */
155+
if (itemConfig.image != null) {
156+
doc.image(itemConfig.image, position.x + 3, position.y + 3);
157+
}
158+
159+
/* title */
160+
doc.fillColor('Black')
161+
.font('Helvetica', 12)
162+
.text(itemConfig.title, position.x + 110, position.y + 7, {
163+
ellipsis: true,
164+
width: (contentSize.width - 4 - 110),
165+
height: 16,
166+
align: 'center'
167+
});
168+
169+
/* description */
170+
doc.fillColor('black')
171+
.font('Helvetica', 10)
172+
.text(itemConfig.description, position.x + 110, position.y + 24, {
173+
ellipsis: true,
174+
width: (contentSize.width - 4 - 110),
175+
height: 74,
176+
align: 'left'
177+
});
178+
179+
/* readmore */
180+
doc.fillColor('black')
181+
.font('Helvetica', 10)
182+
.text('Link Annotation ...', position.x + 110, position.y + 94, {
183+
ellipsis: false,
184+
width: (contentSize.width - 4 - 110),
185+
height: 24,
186+
align: 'right',
187+
link: itemConfig.link,
188+
underline: true
189+
});
190+
191+
doc.restore();
192+
}
193+
}
194+
```
195+
123196
[JavaScript](javascript.controls/CaseItemTemplate.html)
124197
[JQuery](jquery.widgets/CaseItemTemplate.html)
198+
[PDFKit](pdfkit.plugins/UserItemTemplate.html)
199+
[PDFKit Graphics](pdfkit.plugins/UserItemTemplateWithShapes.html)
125200

126201
## Adding link to Item Template
127-
In order to avoid diagram cursor positioning and layout when user clicks on reference add 'stopPropogation' to mouse click event handler of the reference's label.
202+
In order to avoid diagram cursor positioning and layout when user clicks on reference add 'stopPropagation' to mouse click event handler of the reference's label.
128203

129204
```JavaScript
130205
readmore.addEventListener("click", function (e) {
131-
/* Block mouse click propogation in order to avoid layout updates before server postback*/
206+
/* Block mouse click propagation in order to avoid layout updates before server postback*/
132207
primitives.common.stopPropagation(e);
133208
});
134209
```
@@ -137,7 +212,7 @@ In order to avoid diagram cursor positioning and layout when user clicks on refe
137212
[JQuery](jquery.widgets/CaseAddingLinkToItemTemplate.html)
138213

139214
## Adding selection checkbox to Item Template
140-
Chart supports selected items collection on its API, so checkbox element is nessary part of control's functionality. If you want to place it inside of item itemplate instead of having it shown outside as decorator of elemnt boundaries, you have to add `bp-selectioncheckbox` to your checkbox `class` style property.
215+
Chart supports selected items collection on its API, so checkbox element is necessary part of control's functionality. If you want to place it inside of item template instead of having it shown outside as decorator of element boundaries, you have to add `bp-selectioncheckbox` to your checkbox `class` style property.
141216

142217
[JavaScript](javascript.controls/CaseSelectionCheckboxInItemTemplate.html)
143218
[JQuery](jquery.widgets/CaseSelectionCheckboxInItemTemplate.html)

0 commit comments

Comments
 (0)