Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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])
  • Loading branch information...
commit f5bb00fe5c3442e23c3870d14e8315437e9aead5 1 parent 12f29d7
Daniel Dotsenko authored
Showing with 88 additions and 80 deletions.
  1. +34 −26 jspdf.js
  2. +54 −54 jspdf.plugin.standard_fonts_metrics.js
60 jspdf.js
View
@@ -1261,31 +1261,39 @@ function jsPDF(/** String */ orientation, /** String */ unit, /** String */ form
// this is intentional as we allow plugins to override
// built-ins
for (var plugin in jsPDF.API){
- if (plugin !== 'events' && jsPDF.API.hasOwnProperty(plugin)){
- API[plugin] = jsPDF.API[plugin]
- }
- }
-
- // jsPDF.API.events is a JS Object with events catalog likely
- // added by plugins to the jsPDF instantiator.
- // These are always added to the new instance and some ran
- // during instantiation.
- var events_from_plugins = jsPDF.API.events
- for (var e in events_from_plugins){
- if (events_from_plugins.hasOwnProperty(e)) {
- // subscribe takes 3 args: 'topic', function, runonce_flag
- // if undefined, runonce is false.
- // users can attach callback directly,
- // or they can attach an array with [callback, runonce_flag]
- // that's what the "apply" magic is for below.
- events.subscribe.apply(
- events
- , [e].concat(
- typeof events_from_plugins[e] === 'function' ?
- [ events_from_plugins[e] ] :
- events_from_plugins[e]
- ) // it's the topic / event channel name String
- )
+ if (jsPDF.API.hasOwnProperty(plugin)){
+ if (plugin === 'events' && jsPDF.API.events.length) {
+ (function(events, newEvents){
+
+ // jsPDF.API.events is a JS Array of Arrays
+ // where each Array is a pair of event name, handler
+ // Events were added by plugins to the jsPDF instantiator.
+ // These are always added to the new instance and some ran
+ // during instantiation.
+
+ var eventname, handler_and_args
+
+ for (var i = newEvents.length - 1; i !== -1; i--){
+ // subscribe takes 3 args: 'topic', function, runonce_flag
+ // if undefined, runonce is false.
+ // users can attach callback directly,
+ // or they can attach an array with [callback, runonce_flag]
+ // that's what the "apply" magic is for below.
+ eventname = newEvents[i][0]
+ handler_and_args = newEvents[i][1]
+ events.subscribe.apply(
+ events
+ , [eventname].concat(
+ typeof handler_and_args === 'function' ?
+ [ handler_and_args ] :
+ handler_and_args
+ )
+ )
+ }
+ })(events, jsPDF.API.events)
+ } else {
+ API[plugin] = jsPDF.API[plugin]
+ }
}
}
@@ -1328,7 +1336,7 @@ Examples:
var pdfdoc = new jsPDF()
pdfdoc.mymethod() // <- !!!!!!
*/
-jsPDF.API = {'events':{}}
+jsPDF.API = {'events':[]}
return jsPDF
})()
108 jspdf.plugin.standard_fonts_metrics.js
View
@@ -333,63 +333,63 @@ char codes to StandardEncoding character codes. The encoding table is to be used
somewhere around "pdfEscape" call.
*/
-API.events['addFonts'] = function(fontManagementObjects) {
- // fontManagementObjects is {
- // 'fonts':font_ID-keyed hash of font objects
- // , 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
- //}
- var font
- , fontID
- , metrics
- , unicode_section
- , encoding = 'Unicode'
- , encodingBlock
-
- for (fontID in fontManagementObjects.fonts){
- if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
- font = fontManagementObjects.fonts[fontID]
-
- // // we only ship 'Unicode' mappings and metrics. No need for loop.
- // // still, leaving this for the future.
-
- // for (encoding in fontMetrics){
- // if (fontMetrics.hasOwnProperty(encoding)) {
-
- metrics = fontMetrics[encoding][font.PostScriptName]
- if (metrics) {
- if (font.metadata[encoding]) {
- unicode_section = font.metadata[encoding]
- } else {
- unicode_section = font.metadata[encoding] = {}
+API.events.push([
+ 'addFonts'
+ ,function(fontManagementObjects) {
+ // fontManagementObjects is {
+ // 'fonts':font_ID-keyed hash of font objects
+ // , 'dictionary': lookup object, linking ["FontFamily"]['Style'] to font ID
+ //}
+ var font
+ , fontID
+ , metrics
+ , unicode_section
+ , encoding = 'Unicode'
+ , encodingBlock
+
+ for (fontID in fontManagementObjects.fonts){
+ if (fontManagementObjects.fonts.hasOwnProperty(fontID)) {
+ font = fontManagementObjects.fonts[fontID]
+
+ // // we only ship 'Unicode' mappings and metrics. No need for loop.
+ // // still, leaving this for the future.
+
+ // for (encoding in fontMetrics){
+ // if (fontMetrics.hasOwnProperty(encoding)) {
+
+ metrics = fontMetrics[encoding][font.PostScriptName]
+ if (metrics) {
+ if (font.metadata[encoding]) {
+ unicode_section = font.metadata[encoding]
+ } else {
+ unicode_section = font.metadata[encoding] = {}
+ }
+
+ unicode_section.widths = metrics.widths
+ unicode_section.kerning = metrics.kerning
}
-
- unicode_section.widths = metrics.widths
- unicode_section.kerning = metrics.kerning
- }
- // }
- // }
- // for (encoding in encodings){
- // if (encodings.hasOwnProperty(encoding)) {
- encodingBlock = encodings[encoding][font.PostScriptName]
- if (encodingBlock) {
- if (font.metadata[encoding]) {
- unicode_section = font.metadata[encoding]
- } else {
- unicode_section = font.metadata[encoding] = {}
- }
-
- unicode_section.encoding = encodingBlock
- if (encodingBlock.codePages && encodingBlock.codePages.length) {
- font.encoding = encodingBlock.codePages[0]
+ // }
+ // }
+ // for (encoding in encodings){
+ // if (encodings.hasOwnProperty(encoding)) {
+ encodingBlock = encodings[encoding][font.PostScriptName]
+ if (encodingBlock) {
+ if (font.metadata[encoding]) {
+ unicode_section = font.metadata[encoding]
+ } else {
+ unicode_section = font.metadata[encoding] = {}
+ }
+
+ unicode_section.encoding = encodingBlock
+ if (encodingBlock.codePages && encodingBlock.codePages.length) {
+ font.encoding = encodingBlock.codePages[0]
+ }
}
- }
- // }
- // }
+ // }
+ // }
+ }
}
}
-
-
-
-}
+]) // end of adding event handler
})(jsPDF.API);
Please sign in to comment.
Something went wrong with that request. Please try again.