Skip to content

Commit

Permalink
Added a plugin manager.
Browse files Browse the repository at this point in the history
Fire a plugin event on the static PubSub before the first page is added.
  • Loading branch information
Flamenco committed Nov 12, 2014
1 parent a6d7af4 commit a315a4d
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 134 deletions.
18 changes: 17 additions & 1 deletion jspdf.js
Expand Up @@ -1768,6 +1768,7 @@ var jsPDF = (function(global) {
// Add the first page automatically
addFonts();
activeFontKey = 'F1';
jsPDF.plugins.internal.onInitialize(API);
_addPage(format, orientation);

events.publish('initialized');
Expand Down Expand Up @@ -1802,13 +1803,28 @@ var jsPDF = (function(global) {
*/
jsPDF.API = {events:[]};
jsPDF.version = "1.0.0-trunk";

if (typeof define === 'function' && define.amd) {
define('jsPDF', function() {
return jsPDF;
});
} else {
global.jsPDF = jsPDF;
}
jsPDF.plugins = {
register:function(plugin){
this.internal.plugins.push(plugin);
},
internal:{
plugins:[],
onInitialize: function(pdf){
for (var i = 0; i < this.plugins.length; i++) {
var plugin = this.plugins[i];
if (typeof plugin.onInitialize === 'function'){
plugin.onInitialize.call(plugin, pdf);
}
}
},
}
};
return jsPDF;
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this));
27 changes: 18 additions & 9 deletions jspdf.plugin.annotations.js
Expand Up @@ -8,7 +8,7 @@

/**
* There are many types of annotations in a PDF document. Annotations are placed
* on a page at a particular location. They are not 'attached' to an object'
* on a page at a particular location. They are not 'attached' to an object.
* <br />
* This plugin current supports <br />
* <li> Goto Page (set pageNumber in options)
Expand Down Expand Up @@ -36,23 +36,31 @@ function notEmpty(obj) {
(function(jsPDFAPI) {
'use strict';

jsPDFAPI.initAnnotationPlugin = function() {
this.annotationPlugin = {};
var annotationPlugin = {
onInitialize : function(pdf) {
this.installAnnotationPlugin(pdf);
}
};
jsPDF.API.annotationPlugin = annotationPlugin;
jsPDF.plugins.register(annotationPlugin);

annotationPlugin.installAnnotationPlugin = function(pdf) {

this.annotationPlugin.annotations = [];
this.annotations = [];

// TODO remove this after we find a way to subscribe before the
// first page is created.
this.annotationPlugin.annotations[1] = [];
//this.annotations[1] = [];

this.annotationPlugin.f2 = function(number) {
this.f2 = function(number) {
return number.toFixed(2);
};

this.internal.events.subscribe('addPage', function(info) {
pdf.internal.events.subscribe('addPage', function(info) {
this.annotationPlugin.annotations[info.pageNumber] = [];
});

this.internal.events.subscribe('render/page', function(info) {
pdf.internal.events.subscribe('render/page', function(info) {
var pageAnnos = this.annotationPlugin.annotations[info.pageNumber];

var found = false;
Expand All @@ -70,11 +78,12 @@ function notEmpty(obj) {
}

this.internal.write("/Annots [");
var f2 = this.annotationPlugin.f2;
for (var a = 0; a < pageAnnos.length; a++) {
var anno = pageAnnos[a];
var k = this.internal.scaleFactor;
var pageHeight = this.internal.pageSize.height;
var rect = "/Rect [" + this.annotationPlugin.f2(anno.x * k) + " " + this.annotationPlugin.f2((pageHeight - anno.y) * k) + " " + this.annotationPlugin.f2(anno.x + anno.w * k) + " " + this.annotationPlugin.f2(pageHeight - (anno.y + anno.h) * k) + "] ";
var rect = "/Rect [" + f2(anno.x * k) + " " + f2((pageHeight - anno.y) * k) + " " + f2(anno.x + anno.w * k) + " " + f2(pageHeight - (anno.y + anno.h) * k) + "] ";
if (anno.options.url) {
this.internal.write('<</Type /Annot /Subtype /Link ' + rect + '/Border [0 0 0] /A <</S /URI /URI (' + anno.options.url + ') >> >>')
} else if (anno.options.pageNumber) {
Expand Down
254 changes: 134 additions & 120 deletions jspdf.plugin.outline.js
Expand Up @@ -12,151 +12,165 @@
;
(function(jsPDFAPI) {
'use strict';

jsPDFAPI.initOutlinePlugin = function() {

this.outline = {};
this.outline.root = {
children : []
};

this.internal.events.subscribe('postPutResources', function() {
if (this.outline.root.children.length > 0) {
var lines = this.outline.render().split(/\r\n/);
for (var int = 0; int < lines.length; int++) {
var line = lines[int];
if (line.endsWith('obj')){
var oid = line.split(' ')[0];
this.internal.newObjectDeferredBegin(oid);
var outline = {

onInitialize : function(pdf) {

this.installOutlinePlugin(pdf);

pdf.internal.events.subscribe('postPutResources', function() {

var rx = /^(\d+) 0 obj$/;

if (this.outline.root.children.length > 0) {
var lines = pdf.outline.render().split(/\r\n/);
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
var m = rx.exec(line);
if (m != null) {
var oid = m[1];
pdf.internal.newObjectDeferredBegin(oid);
}
pdf.internal.write(line);
}
this.internal.write(line);
}
}
});
});

pdf.internal.events.subscribe('putCatalog', function() {
if (pdf.outline.root.children.length > 0) {
pdf.internal.write("/Outlines", this.outline.makeRef(this.outline.root));
}
});
},

installOutlinePlugin : function(pdf) {

this.internal.events.subscribe('putCatalog', function() {
if (this.outline.root.children.length > 0) {
this.internal.write("/Outlines", this.outline.makeRef(this.outline.root));
}
});

/**
* Options: pageNumber
*/
this.outline.add = function(parent,title,options) {
var item = {
title : title,
options : options,
pdf.outline = {};
pdf.outline.root = {
children : []
};
if (parent == null) {
parent = this.root;

/**
* Options: pageNumber
*/
pdf.outline.add = function(parent,title,options) {
var item = {
title : title,
options : options,
children : []
};
if (parent == null) {
parent = this.root;
}
parent.children.push(item);
return item;
}
parent.children.push(item);
return item;
}

this.outline.render = function() {
this.outline.ctx = {};
this.outline.nextId = 1000;
this.outline.ctx.val = '';
this.outline.ctx.pdf = this;
pdf.outline.render = function() {
this.ctx = {};
this.ctx.val = '';
this.ctx.pdf = pdf;

this.outline.genIds_r(this.outline.root);
this.outline.renderRoot(this.outline.root);
this.outline.renderItems(this.outline.root);
this.genIds_r(this.root);
this.renderRoot(this.root);
this.renderItems(this.root);

return this.outline.ctx.val;
}.bind(this);
return this.ctx.val;
};

this.outline.genIds_r = function(node) {
node.id = this.internal.newObjectDeferred();
for (var i = 0; i < node.children.length; i++) {
this.outline.genIds_r(node.children[i]);
}
}.bind(this);

this.outline.renderRoot = function(node) {
this.objStart(node);
this.line('/Type /Outlines');
if (node.children.length > 0) {
this.line('/First ' + this.makeRef(node.children[0]));
this.line('/Last ' + this.makeRef(node.children[node.children.length - 1]));
}
this.line('/Count ' + this.count_r({
count : 0
}, node));
this.objEnd();
}
pdf.outline.genIds_r = function(node) {
node.id = pdf.internal.newObjectDeferred();
for (var i = 0; i < node.children.length; i++) {
this.genIds_r(node.children[i]);
}
};

this.outline.renderItems = function(node) {
for (var i = 0; i < node.children.length; i++) {
var item = node.children[i];
this.objStart(item);
pdf.outline.renderRoot = function(node) {
this.objStart(node);
this.line('/Type /Outlines');
if (node.children.length > 0) {
this.line('/First ' + this.makeRef(node.children[0]));
this.line('/Last ' + this.makeRef(node.children[node.children.length - 1]));
}
this.line('/Count ' + this.count_r({
count : 0
}, node));
this.objEnd();
};

this.line('/Title ' + this.makeString(item.title));
pdf.outline.renderItems = function(node) {
for (var i = 0; i < node.children.length; i++) {
var item = node.children[i];
this.objStart(item);

this.line('/Parent ' + this.makeRef(node));
if (i > 0) {
this.line('/Prev ' + this.makeRef(node.children[i - 1]));
}
if (i < node.children.length - 1) {
this.line('/Next ' + this.makeRef(node.children[i + 1]));
}
if (item.children.length > 0) {
this.line('/First ' + this.makeRef(item.children[0]));
this.line('/Last ' + this.makeRef(item.children[item.children.length - 1]));
}
this.line('/Title ' + this.makeString(item.title));

var count = this.count = this.count_r({
count : 0
}, item);
if (count > 0) {
this.line('/Count ' + count);
}
this.line('/Parent ' + this.makeRef(node));
if (i > 0) {
this.line('/Prev ' + this.makeRef(node.children[i - 1]));
}
if (i < node.children.length - 1) {
this.line('/Next ' + this.makeRef(node.children[i + 1]));
}
if (item.children.length > 0) {
this.line('/First ' + this.makeRef(item.children[0]));
this.line('/Last ' + this.makeRef(item.children[item.children.length - 1]));
}

var count = this.count = this.count_r({
count : 0
}, item);
if (count > 0) {
this.line('/Count ' + count);
}

if (item.options) {
if (item.options.pageNumber) {
this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.height + ' 0]');
//this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /Fit]');
if (item.options) {
if (item.options.pageNumber) {
this.line('/Dest ' + '[' + (item.options.pageNumber - 1) + ' /XYZ 0 ' + this.ctx.pdf.internal.pageSize.height + ' 0]');
// this.line('/Dest ' + '[' +
// (item.options.pageNumber -
// 1) + ' /Fit]');
}
}
this.objEnd();
}
this.objEnd();
}
for (var i = 0; i < node.children.length; i++) {
var item = node.children[i];
this.renderItems(item);
}
}
for (var i = 0; i < node.children.length; i++) {
var item = node.children[i];
this.renderItems(item);
}
};

this.outline.line = function(text) {
this.ctx.val += text + '\r\n';
}
pdf.outline.line = function(text) {
this.ctx.val += text + '\r\n';
};

this.outline.makeRef = function(node) {
return node.id + ' 0 R';
}
pdf.outline.makeRef = function(node) {
return node.id + ' 0 R';
};

this.outline.makeString = function(val) {
return '(' + this.internal.pdfEscape(val) + ')';
}.bind(this);
pdf.outline.makeString = function(val) {
return '(' + pdf.internal.pdfEscape(val) + ')';
};

this.outline.objStart = function(node) {
this.ctx.val += '\r\n' + node.id + ' 0 obj' + '\r\n<<\r\n';
}
pdf.outline.objStart = function(node) {
this.ctx.val += '\r\n' + node.id + ' 0 obj' + '\r\n<<\r\n';
};

this.outline.objEnd = function(node) {
this.ctx.val += '>> \r\n' + 'endobj' + '\r\n';
}
pdf.outline.objEnd = function(node) {
this.ctx.val += '>> \r\n' + 'endobj' + '\r\n';
};

this.outline.count_r = function(ctx,node) {
for (var i = 0; i < node.children.length; i++) {
ctx.count++;
this.count_r(ctx, node.children[i]);
}
return ctx.count;
pdf.outline.count_r = function(ctx,node) {
for (var i = 0; i < node.children.length; i++) {
ctx.count++;
this.count_r(ctx, node.children[i]);
}
return ctx.count;
};
}
}
jsPDF.API.outline = outline;
jsPDF.plugins.register(outline);

return this;
})(jsPDF.API);

0 comments on commit a315a4d

Please sign in to comment.