Skip to content

Commit f5bb00f

Browse files
author
Daniel Dotsenko
committed
Fixing design flaw external event attachment mechanism
jsPDF.API.events was {} where new events would attach using [eventname] = handler Now it is obvious that only last of several handlers fighting for same event would win. Switching for less pretty, but working array of pairs model jsPDF.API.events = [[e,h], [e,h]...] Instead of jsPDF.API.events[e] = h one would jsPDF.API.events.push([e,h])
1 parent 12f29d7 commit f5bb00f

File tree

2 files changed

+88
-80
lines changed

2 files changed

+88
-80
lines changed

jspdf.js

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,31 +1261,39 @@ function jsPDF(/** String */ orientation, /** String */ unit, /** String */ form
12611261
// this is intentional as we allow plugins to override
12621262
// built-ins
12631263
for (var plugin in jsPDF.API){
1264-
if (plugin !== 'events' && jsPDF.API.hasOwnProperty(plugin)){
1265-
API[plugin] = jsPDF.API[plugin]
1266-
}
1267-
}
1268-
1269-
// jsPDF.API.events is a JS Object with events catalog likely
1270-
// added by plugins to the jsPDF instantiator.
1271-
// These are always added to the new instance and some ran
1272-
// during instantiation.
1273-
var events_from_plugins = jsPDF.API.events
1274-
for (var e in events_from_plugins){
1275-
if (events_from_plugins.hasOwnProperty(e)) {
1276-
// subscribe takes 3 args: 'topic', function, runonce_flag
1277-
// if undefined, runonce is false.
1278-
// users can attach callback directly,
1279-
// or they can attach an array with [callback, runonce_flag]
1280-
// that's what the "apply" magic is for below.
1281-
events.subscribe.apply(
1282-
events
1283-
, [e].concat(
1284-
typeof events_from_plugins[e] === 'function' ?
1285-
[ events_from_plugins[e] ] :
1286-
events_from_plugins[e]
1287-
) // it's the topic / event channel name String
1288-
)
1264+
if (jsPDF.API.hasOwnProperty(plugin)){
1265+
if (plugin === 'events' && jsPDF.API.events.length) {
1266+
(function(events, newEvents){
1267+
1268+
// jsPDF.API.events is a JS Array of Arrays
1269+
// where each Array is a pair of event name, handler
1270+
// Events were added by plugins to the jsPDF instantiator.
1271+
// These are always added to the new instance and some ran
1272+
// during instantiation.
1273+
1274+
var eventname, handler_and_args
1275+
1276+
for (var i = newEvents.length - 1; i !== -1; i--){
1277+
// subscribe takes 3 args: 'topic', function, runonce_flag
1278+
// if undefined, runonce is false.
1279+
// users can attach callback directly,
1280+
// or they can attach an array with [callback, runonce_flag]
1281+
// that's what the "apply" magic is for below.
1282+
eventname = newEvents[i][0]
1283+
handler_and_args = newEvents[i][1]
1284+
events.subscribe.apply(
1285+
events
1286+
, [eventname].concat(
1287+
typeof handler_and_args === 'function' ?
1288+
[ handler_and_args ] :
1289+
handler_and_args
1290+
)
1291+
)
1292+
}
1293+
})(events, jsPDF.API.events)
1294+
} else {
1295+
API[plugin] = jsPDF.API[plugin]
1296+
}
12891297
}
12901298
}
12911299

@@ -1328,7 +1336,7 @@ Examples:
13281336
var pdfdoc = new jsPDF()
13291337
pdfdoc.mymethod() // <- !!!!!!
13301338
*/
1331-
jsPDF.API = {'events':{}}
1339+
jsPDF.API = {'events':[]}
13321340

13331341
return jsPDF
13341342
})()

jspdf.plugin.standard_fonts_metrics.js

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -333,63 +333,63 @@ char codes to StandardEncoding character codes. The encoding table is to be used
333333
somewhere around "pdfEscape" call.
334334
*/
335335

336-
API.events['addFonts'] = function(fontManagementObjects) {
337-
// fontManagementObjects is {
338-
// 'fonts':font_ID-keyed hash of font objects
339-
// , 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
340-
//}
341-
var font
342-
, fontID
343-
, metrics
344-
, unicode_section
345-
, encoding = 'Unicode'
346-
, encodingBlock
347-
348-
for (fontID in fontManagementObjects.fonts){
349-
if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
350-
font = fontManagementObjects.fonts[fontID]
351-
352-
// // we only ship 'Unicode' mappings and metrics. No need for loop.
353-
// // still, leaving this for the future.
354-
355-
// for (encoding in fontMetrics){
356-
// if (fontMetrics.hasOwnProperty(encoding)) {
357-
358-
metrics = fontMetrics[encoding][font.PostScriptName]
359-
if (metrics) {
360-
if (font.metadata[encoding]) {
361-
unicode_section = font.metadata[encoding]
362-
} else {
363-
unicode_section = font.metadata[encoding] = {}
336+
API.events.push([
337+
'addFonts'
338+
,function(fontManagementObjects) {
339+
// fontManagementObjects is {
340+
// 'fonts':font_ID-keyed hash of font objects
341+
// , 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
342+
//}
343+
var font
344+
, fontID
345+
, metrics
346+
, unicode_section
347+
, encoding = 'Unicode'
348+
, encodingBlock
349+
350+
for (fontID in fontManagementObjects.fonts){
351+
if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
352+
font = fontManagementObjects.fonts[fontID]
353+
354+
// // we only ship 'Unicode' mappings and metrics. No need for loop.
355+
// // still, leaving this for the future.
356+
357+
// for (encoding in fontMetrics){
358+
// if (fontMetrics.hasOwnProperty(encoding)) {
359+
360+
metrics = fontMetrics[encoding][font.PostScriptName]
361+
if (metrics) {
362+
if (font.metadata[encoding]) {
363+
unicode_section = font.metadata[encoding]
364+
} else {
365+
unicode_section = font.metadata[encoding] = {}
366+
}
367+
368+
unicode_section.widths = metrics.widths
369+
unicode_section.kerning = metrics.kerning
364370
}
365-
366-
unicode_section.widths = metrics.widths
367-
unicode_section.kerning = metrics.kerning
368-
}
369-
// }
370-
// }
371-
// for (encoding in encodings){
372-
// if (encodings.hasOwnProperty(encoding)) {
373-
encodingBlock = encodings[encoding][font.PostScriptName]
374-
if (encodingBlock) {
375-
if (font.metadata[encoding]) {
376-
unicode_section = font.metadata[encoding]
377-
} else {
378-
unicode_section = font.metadata[encoding] = {}
379-
}
380-
381-
unicode_section.encoding = encodingBlock
382-
if (encodingBlock.codePages && encodingBlock.codePages.length) {
383-
font.encoding = encodingBlock.codePages[0]
371+
// }
372+
// }
373+
// for (encoding in encodings){
374+
// if (encodings.hasOwnProperty(encoding)) {
375+
encodingBlock = encodings[encoding][font.PostScriptName]
376+
if (encodingBlock) {
377+
if (font.metadata[encoding]) {
378+
unicode_section = font.metadata[encoding]
379+
} else {
380+
unicode_section = font.metadata[encoding] = {}
381+
}
382+
383+
unicode_section.encoding = encodingBlock
384+
if (encodingBlock.codePages && encodingBlock.codePages.length) {
385+
font.encoding = encodingBlock.codePages[0]
386+
}
384387
}
385-
}
386-
// }
387-
// }
388+
// }
389+
// }
390+
}
388391
}
389392
}
390-
391-
392-
393-
}
393+
]) // end of adding event handler
394394

395395
})(jsPDF.API);

0 commit comments

Comments
 (0)