diff --git a/lib/Viewer.js b/lib/Viewer.js index 52b7840d..61226b35 100644 --- a/lib/Viewer.js +++ b/lib/Viewer.js @@ -76,16 +76,16 @@ function ensureUnit(val) { * @param {ModdleElement} definitions * @param {String} diagramId * - * @return {Diagram|undefined} + * @return {Diagram|null} */ function findDiagram(definitions, diagramId) { if (!diagramId) { - return; + return null; } return find(definitions.diagrams, function(element) { return element.id === diagramId; - }); + }) || null; } /** @@ -203,8 +203,7 @@ Viewer.prototype.importXML = function(xml, diagramId, done) { context: context }) || definitions; - var parseWarnings = context.warnings, - diagram; + var parseWarnings = context.warnings; if (err) { err = checkValidationError(err); @@ -214,17 +213,9 @@ Viewer.prototype.importXML = function(xml, diagramId, done) { return done(err, parseWarnings); } - diagram = findDiagram(definitions, diagramId); + self._setDefinitions(definitions); - if (diagramId && !diagram) { - err = new Error('BPMNDiagram not found'); - - self._emit('import.done', { error: err, warnings: parseWarnings || [] }); - - return done(err); - } - - self.importDefinitions(definitions, diagram, function(err, importWarnings) { + self.open(diagramId, function(err, importWarnings) { var allWarnings = [].concat(parseWarnings, importWarnings || []); self._emit('import.done', { error: err, warnings: allWarnings }); @@ -234,6 +225,60 @@ Viewer.prototype.importXML = function(xml, diagramId, done) { }); }; +/** + * Open diagram of previously imported XML. + * + * Once finished the viewer reports back the result to the + * provided callback function with (err, warnings). + * + * ## Life-Cycle Events + * + * During switch the viewer will fire life-cycle events: + * + * * import.render.start (graphical import start) + * * import.render.complete (graphical import finished) + * + * You can use these events to hook into the life-cycle. + * + * @param {String|Diagram} [diagram] id or the diagram to open + * @param {Function} [done] invoked with (err, warnings=[]) + */ +Viewer.prototype.open = function(diagram, done) { + + if (isFunction(diagram)) { + done = diagram; + diagram = null; + } + + var definitions = this._definitions; + + // done is optional + done = done || function() {}; + + if (!definitions) { + return done(new Error('no XML imported')); + } + + if (typeof diagram === 'string') { + diagram = findDiagram(definitions, diagram); + + if (!diagram) { + return done(new Error('no diagram to display')); + } + } + + // catch synchronous exceptions during #clear() + try { + // clear existing rendered diagram + this.clear(); + } catch (error) { + return done(error); + } + + // perform graphical import + return importBpmnDiagram(this, definitions, diagram, done); +}; + /** * Export the currently displayed BPMN 2.0 diagram as * a BPMN 2.0 XML document. @@ -385,28 +430,8 @@ Viewer.prototype.saveSVG = function(options, done) { */ -Viewer.prototype.importDefinitions = function(definitions, diagram, done) { - - if (isFunction(diagram)) { - done = diagram; - diagram = null; - } - - // catch synchronous exceptions during #clear() - try { - if (this._definitions) { - // clear existing rendered diagram - this.clear(); - } - - // update definitions - this._definitions = definitions; - } catch (e) { - return done(e); - } - - // perform graphical import - return importBpmnDiagram(this, definitions, diagram, done); +Viewer.prototype._setDefinitions = function(definitions) { + this._definitions = definitions; }; Viewer.prototype.getModules = function() { diff --git a/test/spec/ViewerSpec.js b/test/spec/ViewerSpec.js index b39454a5..3548ac5c 100644 --- a/test/spec/ViewerSpec.js +++ b/test/spec/ViewerSpec.js @@ -718,7 +718,7 @@ describe('Viewer', function() { // then expect(err).to.exist; - expect(err.message).to.eql('BPMNDiagram not found'); + expect(err.message).to.eql('no diagram to display'); done(); }); @@ -744,6 +744,134 @@ describe('Viewer', function() { }); + describe('#open', function() { + + var diagramId1 = 'Diagram_80fecfcd-0165-4c36-90b6-3ea384265fe7', + diagramId2 = 'Diagram_94435ba7-4027-4df9-ad3b-df1f6e068e5e', + xml = require('../fixtures/bpmn/multiple-diagrams.bpmn'); + + it('should open another diagram', function(done) { + + // when + createViewer(xml, diagramId1, function(err, warnings, viewer) { + + // then + expect(err).not.to.exist; + expect(warnings).to.be.empty; + + var definitions = viewer.getDefinitions(); + + expect(definitions).to.exist; + + viewer.open(diagramId2, function(err, warnings) { + + // then + expect(err).not.to.exist; + expect(warnings).to.be.empty; + + var definitions = viewer.getDefinitions(); + + expect(definitions).to.exist; + + done(); + }); + }); + }); + + + it('should complete with error if xml was not imported', function(done) { + + // given + var viewer = new Viewer(); + + // when + viewer.open(function(err) { + + // then + expect(err).to.exist; + expect(err.message).to.eql('no XML imported'); + + var definitions = viewer.getDefinitions(); + + expect(definitions).to.not.exist; + + done(); + }); + + }); + + + it('should open with error if diagram does not exist', function(done) { + + // when + createViewer(xml, diagramId1, function(err, warnings, viewer) { + + // then + expect(err).not.to.exist; + expect(warnings).to.be.empty; + + var definitions = viewer.getDefinitions(); + + expect(definitions).to.exist; + + viewer.open('Diagram_IDontExist', function(err) { + + // then + expect(err).to.exist; + expect(err.message).to.eql('no diagram to display'); + + // definitions stay the same + expect(viewer.getDefinitions()).to.eql(definitions); + + done(); + }); + }); + }); + + + it('should emit events', function(done) { + + // given + var viewer = new Viewer({ container: container }); + + var events = []; + + // when + viewer.importXML(xml, diagramId1, function(err) { + + // when + viewer.on([ + 'import.parse.start', + 'import.parse.complete', + 'import.render.start', + 'import.render.complete', + 'import.done' + ], function(e) { + // log event type + event arguments + events.push([ + e.type, + Object.keys(e).filter(function(key) { + return key !== 'type'; + }) + ]); + }); + + viewer.open(diagramId2, function(err) { + + // then + expect(events).to.eql([ + [ 'import.render.start', [ 'definitions' ] ], + [ 'import.render.complete', [ 'error', 'warnings' ] ] + ]); + + done(err); + }); + }); + }); + + }); + + describe('#saveXML', function() { it('should export XML', function(done) {